<commit_before>/// The tokenizer for the query interpreter

use error::*;
use std::rc::Rc;

#[derive(Debug, PartialEq, Eq)]
pub enum Token {
    Identifier {
        ident: String,
        next: Option<Rc<Token>>
    },

    Index {
        idx: i64,
        next: Option<Rc<Token>>
    }
}

impl Token {

    pub fn set_next(&mut self, token: Token) {
        match self {
            &mut Token::Identifier { next: ref mut next, .. } => *next = Some(Rc::new(token)),
            &mut Token::Index { next: ref mut next, .. }      => *next = Some(Rc::new(token)),
        }
    }

    #[cfg(test)]
    pub fn identifier(&self) -> &String {
        match self {
            &Token::Identifier { ident: ref ident, .. } => &ident,
            _ => unreachable!(),
        }
    }

    #[cfg(test)]
    pub fn idx(&self) -> i64 {
        match self {
            &Token::Index { idx: i, .. } => i,
            _ => unreachable!(),
        }
    }
}

pub fn tokenize_with_seperator(query: &String, seperator: char) -> Result<Token> {
    use std::str::Split;

    /// Creates a Token object from a string
    ///
    /// # Panics
    ///
    /// * If the internal regex does not compile (should never happen)
    /// * If the token is non-valid (that is, a array index with a non-i64)
    /// * If the regex does not find anything
    /// * If the integer in the brackets (`[]`) cannot be parsed to a valid i64
    ///
    /// # Incorrect behaviour
    ///
    /// * If the regex finds multiple captures
    ///
    /// # Returns
    ///
    /// The `Token` object with the correct identifier/index for this token and no next token.
    ///
    fn mk_token_object(s: &str) -> Result<Token> {
        use regex::Regex;
        use std::str::FromStr;

        lazy_static! {
            static ref RE: Regex = Regex::new(r"^\[-?\d+\]$").unwrap();
        }

        if s.as_bytes()[0] == b'[' && s.as_bytes()[s.len() - 1] == b']' {
            match RE.captures(s) {
                None => return Err(Error::from(ErrorKind::ArrayAccessWithoutIndex)),
                Some(captures) => {
                    match captures.get(0) {
                        None => Ok(Token::Identifier { ident: String::from(s), next: None }),
                        Some(mtch) => {
                            let mtch = mtch.as_str().replace("[","").replace("]","");
                            let i : i64 = FromStr::from_str(&mtch).unwrap(); // save because regex
                            Ok(Token::Index {
                                idx: i,
                                next: None,
                            })
                        }
                    }
                }
            }
        } else {
            Ok(Token::Identifier { ident: String::from(s), next: None })
        }

    }

    fn build_token_tree(split: &mut Split<char>, last: &mut Token) -> Result<()> {
        match split.next() {
            None        => { /* No more tokens */ }
            Some(token) => {
                let mut token = try!(mk_token_object(token));
                build_token_tree(split, &mut token);
                last.set_next(token);
            }
        }
        Ok(())
    }

    if query.is_empty() {
        return Err(Error::from(ErrorKind::EmptyQueryError));
    }

    let mut tokens = query.split(seperator);

    match tokens.next() {
        None        => Err(Error::from(ErrorKind::EmptyQueryError)),
        Some(token) => {
            if token.len() == 0 {
                return Err(Error::from(ErrorKind::EmptyIdentifier));
            }
            let mut tok = try!(mk_token_object(token));
            let _       = try!(build_token_tree(&mut tokens, &mut tok));
            Ok(tok)
        }
    }
}

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

    use std::ops::Deref;

    #[test]
    fn test_tokenize_empty_query_to_error() {
        let tokens = tokenize_with_seperator(&String::from(""), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyQueryError { .. }));
    }

    #[test]
    fn test_tokenize_seperator_only() {
        let tokens = tokenize_with_seperator(&String::from("."), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyIdentifier { .. }));
    }

    #[test]
    fn test_tokenize_array_brackets_only() {
        let tokens = tokenize_with_seperator(&String::from("[]"), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::ArrayAccessWithoutIndex { .. }));
    }

    #[test]
    fn test_tokenize_identifiers_with_array_brackets_only() {
        let tokens = tokenize_with_seperator(&String::from("a.b.c.[]"), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::ArrayAccessWithoutIndex { .. }));
    }

    #[test]
    fn test_tokenize_identifiers_in_array_brackets() {
        let tokens = tokenize_with_seperator(&String::from("[a]"), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::ArrayAccessWithoutIndex { .. }));
    }

    #[test]
    fn test_tokenize_single_token_query() {
        let tokens = tokenize_with_seperator(&String::from("example"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier {
                ident: ident,
                next: None
            } => {
                assert_eq!(String::from("example"), ident);
                true
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_double_token_query() {
        let tokens = tokenize_with_seperator(&String::from("a.b"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                assert_eq!("b", next.deref().identifier());
                match next.deref() {
                    &Token::Identifier { next: None, .. } => true,
                    _ => false
                }
            },
            _ => false,
        });
        assert_eq!("a", tokens.identifier());
    }

    #[test]
    fn test_tokenize_ident_then_array_query() {
        let tokens = tokenize_with_seperator(&String::from("a.[0]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());
        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                match next.deref() {
                    &Token::Index { idx: 0, next: None } => true,
                    _ => false
                }
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_many_idents_then_array_query() {
        use std::ops::Deref;

        let tokens = tokenize_with_seperator(&String::from("a.b.c.[1000]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());

        let expected =
            Token::Identifier {
                ident: String::from("a"),
                next: Some(Rc::new(Token::Identifier {
                    ident: String::from("b"),
                    next: Some(Rc::new(Token::Identifier {
                        ident: String::from("c"),
                        next: Some(Rc::new(Token::Index {
                            idx: 1000,
                            next: None,
                        })),
                    })),
                })),
            };

        assert_eq!(expected, tokens);
    }

    quickcheck! {
        fn test_array_index(i: i64) -> bool {
            match tokenize_with_seperator(&format!("[{}]", i), '.') {
                Ok(Token::Index {
                    idx: i,
                    next: None,
                }) => true,
                _ => false,
            }
        }
    }

}
<commit_msg>Impl tokenize_with_seperator to fix test_tokenize_identifiers_with_array_brackets_only<commit_after>/// The tokenizer for the query interpreter

use error::*;
use std::rc::Rc;

#[derive(Debug, PartialEq, Eq)]
pub enum Token {
    Identifier {
        ident: String,
        next: Option<Rc<Token>>
    },

    Index {
        idx: i64,
        next: Option<Rc<Token>>
    }
}

impl Token {

    pub fn set_next(&mut self, token: Token) {
        match self {
            &mut Token::Identifier { next: ref mut next, .. } => *next = Some(Rc::new(token)),
            &mut Token::Index { next: ref mut next, .. }      => *next = Some(Rc::new(token)),
        }
    }

    #[cfg(test)]
    pub fn identifier(&self) -> &String {
        match self {
            &Token::Identifier { ident: ref ident, .. } => &ident,
            _ => unreachable!(),
        }
    }

    #[cfg(test)]
    pub fn idx(&self) -> i64 {
        match self {
            &Token::Index { idx: i, .. } => i,
            _ => unreachable!(),
        }
    }
}

pub fn tokenize_with_seperator(query: &String, seperator: char) -> Result<Token> {
    use std::str::Split;

    /// Creates a Token object from a string
    ///
    /// # Panics
    ///
    /// * If the internal regex does not compile (should never happen)
    /// * If the token is non-valid (that is, a array index with a non-i64)
    /// * If the regex does not find anything
    /// * If the integer in the brackets (`[]`) cannot be parsed to a valid i64
    ///
    /// # Incorrect behaviour
    ///
    /// * If the regex finds multiple captures
    ///
    /// # Returns
    ///
    /// The `Token` object with the correct identifier/index for this token and no next token.
    ///
    fn mk_token_object(s: &str) -> Result<Token> {
        use regex::Regex;
        use std::str::FromStr;

        lazy_static! {
            static ref RE: Regex = Regex::new(r"^\[-?\d+\]$").unwrap();
        }

        if s.as_bytes()[0] == b'[' && s.as_bytes()[s.len() - 1] == b']' {
            match RE.captures(s) {
                None => return Err(Error::from(ErrorKind::ArrayAccessWithoutIndex)),
                Some(captures) => {
                    match captures.get(0) {
                        None => Ok(Token::Identifier { ident: String::from(s), next: None }),
                        Some(mtch) => {
                            let mtch = mtch.as_str().replace("[","").replace("]","");
                            let i : i64 = FromStr::from_str(&mtch).unwrap(); // save because regex
                            Ok(Token::Index {
                                idx: i,
                                next: None,
                            })
                        }
                    }
                }
            }
        } else {
            Ok(Token::Identifier { ident: String::from(s), next: None })
        }

    }

    fn build_token_tree(split: &mut Split<char>, last: &mut Token) -> Result<()> {
        match split.next() {
            None        => { /* No more tokens */ }
            Some(token) => {
                let mut token = try!(mk_token_object(token));
                try!(build_token_tree(split, &mut token));
                last.set_next(token);
            }
        }
        Ok(())
    }

    if query.is_empty() {
        return Err(Error::from(ErrorKind::EmptyQueryError));
    }

    let mut tokens = query.split(seperator);

    match tokens.next() {
        None        => Err(Error::from(ErrorKind::EmptyQueryError)),
        Some(token) => {
            if token.len() == 0 {
                return Err(Error::from(ErrorKind::EmptyIdentifier));
            }
            let mut tok = try!(mk_token_object(token));
            let _       = try!(build_token_tree(&mut tokens, &mut tok));
            Ok(tok)
        }
    }
}

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

    use std::ops::Deref;

    #[test]
    fn test_tokenize_empty_query_to_error() {
        let tokens = tokenize_with_seperator(&String::from(""), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyQueryError { .. }));
    }

    #[test]
    fn test_tokenize_seperator_only() {
        let tokens = tokenize_with_seperator(&String::from("."), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyIdentifier { .. }));
    }

    #[test]
    fn test_tokenize_array_brackets_only() {
        let tokens = tokenize_with_seperator(&String::from("[]"), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::ArrayAccessWithoutIndex { .. }));
    }

    #[test]
    fn test_tokenize_identifiers_with_array_brackets_only() {
        let tokens = tokenize_with_seperator(&String::from("a.b.c.[]"), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::ArrayAccessWithoutIndex { .. }));
    }

    #[test]
    fn test_tokenize_identifiers_in_array_brackets() {
        let tokens = tokenize_with_seperator(&String::from("[a]"), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::ArrayAccessWithoutIndex { .. }));
    }

    #[test]
    fn test_tokenize_single_token_query() {
        let tokens = tokenize_with_seperator(&String::from("example"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier {
                ident: ident,
                next: None
            } => {
                assert_eq!(String::from("example"), ident);
                true
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_double_token_query() {
        let tokens = tokenize_with_seperator(&String::from("a.b"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                assert_eq!("b", next.deref().identifier());
                match next.deref() {
                    &Token::Identifier { next: None, .. } => true,
                    _ => false
                }
            },
            _ => false,
        });
        assert_eq!("a", tokens.identifier());
    }

    #[test]
    fn test_tokenize_ident_then_array_query() {
        let tokens = tokenize_with_seperator(&String::from("a.[0]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());
        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                match next.deref() {
                    &Token::Index { idx: 0, next: None } => true,
                    _ => false
                }
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_many_idents_then_array_query() {
        use std::ops::Deref;

        let tokens = tokenize_with_seperator(&String::from("a.b.c.[1000]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());

        let expected =
            Token::Identifier {
                ident: String::from("a"),
                next: Some(Rc::new(Token::Identifier {
                    ident: String::from("b"),
                    next: Some(Rc::new(Token::Identifier {
                        ident: String::from("c"),
                        next: Some(Rc::new(Token::Index {
                            idx: 1000,
                            next: None,
                        })),
                    })),
                })),
            };

        assert_eq!(expected, tokens);
    }

    quickcheck! {
        fn test_array_index(i: i64) -> bool {
            match tokenize_with_seperator(&format!("[{}]", i), '.') {
                Ok(Token::Index {
                    idx: i,
                    next: None,
                }) => true,
                _ => false,
            }
        }
    }

}
<|endoftext|>


<commit_before>pub mod fs;

use pulldown_cmark::{Parser, Event, Tag, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES};
use std::borrow::Cow;

///
///
/// Wrapper around the pulldown-cmark parser and renderer to render markdown

pub fn render_markdown(text: &str, curly_quotes: bool) -> String {
    let mut s = String::with_capacity(text.len() * 3 / 2);

    let mut opts = Options::empty();
    opts.insert(OPTION_ENABLE_TABLES);
    opts.insert(OPTION_ENABLE_FOOTNOTES);

    let p = Parser::new_ext(text, opts);
    let mut converter = EventQuoteConverter::new(curly_quotes);
    let events = p.map(|event| converter.convert(event));
    html::push_html(&mut s, events);
    s
}

struct EventQuoteConverter {
    enabled: bool,
    convert_text: bool,
}

impl EventQuoteConverter {
    fn new(enabled: bool) -> Self {
        EventQuoteConverter { enabled: enabled, convert_text: true }
    }

    fn convert<'a>(&mut self, event: Event<'a>) -> Event<'a> {
        if !self.enabled {
            return event;
        }

        match event {
            Event::Start(Tag::CodeBlock(_)) |
            Event::Start(Tag::Code) => {
                self.convert_text = false;
                event
            },
            Event::End(Tag::CodeBlock(_)) |
            Event::End(Tag::Code) => {
                self.convert_text = true;
                event
            },
            Event::Text(ref text) if self.convert_text => Event::Text(Cow::from(convert_quotes_to_curly(text))),
            _ => event,
        }
    }
}

fn convert_quotes_to_curly(original_text: &str) -> String {
    // We'll consider the start to be "whitespace".
    let mut preceded_by_whitespace = true;

    original_text
        .chars()
        .map(|original_char| {
            let converted_char = match original_char {
                '\'' => if preceded_by_whitespace { '‘' } else { '’' },
                '"' => if preceded_by_whitespace { '“' } else { '”' },
                _ => original_char,
            };

            preceded_by_whitespace = original_char.is_whitespace();

            converted_char
        })
        .collect()
}

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

        #[test]
        fn it_can_keep_quotes_straight() {
            assert_eq!(render_markdown("'one'", false), "
'one'
\n");
        }

        #[test]
        fn it_can_make_quotes_curly_except_when_they_are_in_code() {
            let input = r#"
'one'
```
'two'
```
`'three'` 'four'"#;
            let expected = r#"
‘one’

'two'

'three' ‘four’

"#;
            assert_eq!(render_markdown(input, true), expected);
        }
    }

    mod convert_quotes_to_curly {
        use super::super::convert_quotes_to_curly;

        #[test]
        fn it_converts_single_quotes() {
            assert_eq!(convert_quotes_to_curly("'one', 'two'"), "‘one’, ‘two’");
        }

        #[test]
        fn it_converts_double_quotes() {
            assert_eq!(convert_quotes_to_curly(r#""one", "two""#), "“one”, “two”");
        }

        #[test]
        fn it_treats_tab_as_whitespace() {
            assert_eq!(convert_quotes_to_curly("\t'one'"), "\t‘one’");
        }
    }
}
<commit_msg>fixed missing playpen css class when codeblock properties had whitespace<commit_after>pub mod fs;

use pulldown_cmark::{Parser, Event, Tag, html, Options, OPTION_ENABLE_TABLES, OPTION_ENABLE_FOOTNOTES};
use std::borrow::Cow;

///
///
/// Wrapper around the pulldown-cmark parser and renderer to render markdown

pub fn render_markdown(text: &str, curly_quotes: bool) -> String {
    let mut s = String::with_capacity(text.len() * 3 / 2);

    let mut opts = Options::empty();
    opts.insert(OPTION_ENABLE_TABLES);
    opts.insert(OPTION_ENABLE_FOOTNOTES);

    let p = Parser::new_ext(text, opts);
    let mut converter = EventQuoteConverter::new(curly_quotes);
    let events = p.map(clean_codeblock_headers).map(|event| converter.convert(event));

    html::push_html(&mut s, events);
    s
}

struct EventQuoteConverter {
    enabled: bool,
    convert_text: bool,
}

impl EventQuoteConverter {
    fn new(enabled: bool) -> Self {
        EventQuoteConverter { enabled: enabled, convert_text: true }
    }

    fn convert<'a>(&mut self, event: Event<'a>) -> Event<'a> {
        if !self.enabled {
            return event;
        }

        match event {
            Event::Start(Tag::CodeBlock(_)) |
            Event::Start(Tag::Code) => {
                self.convert_text = false;
                event
            },
            Event::End(Tag::CodeBlock(_)) |
            Event::End(Tag::Code) => {
                self.convert_text = true;
                event
            },
            Event::Text(ref text) if self.convert_text => Event::Text(Cow::from(convert_quotes_to_curly(text))),
            _ => event,
        }
    }
}

fn clean_codeblock_headers(event: Event) -> Event {
    match event {
        Event::Start(Tag::CodeBlock(ref info)) => {
            let info: String = info
                .chars()
                .filter(|ch| !ch.is_whitespace())
                .collect();

            Event::Start(Tag::CodeBlock(Cow::from(info)))
        },
        _ => event,
    }
}

fn convert_quotes_to_curly(original_text: &str) -> String {
    // We'll consider the start to be "whitespace".
    let mut preceded_by_whitespace = true;

    original_text
        .chars()
        .map(|original_char| {
            let converted_char = match original_char {
                '\'' => if preceded_by_whitespace { '‘' } else { '’' },
                '"' => if preceded_by_whitespace { '“' } else { '”' },
                _ => original_char,
            };

            preceded_by_whitespace = original_char.is_whitespace();

            converted_char
        })
        .collect()
}

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

        #[test]
        fn it_can_keep_quotes_straight() {
            assert_eq!(render_markdown("'one'", false), "
'one'
\n");
        }

        #[test]
        fn it_can_make_quotes_curly_except_when_they_are_in_code() {
            let input = r#"
'one'
```
'two'
```
`'three'` 'four'"#;
            let expected = r#"
‘one’

'two'

'three' ‘four’

"#;
            assert_eq!(render_markdown(input, true), expected);
        }

        #[test]
        fn whitespace_outside_of_codeblock_header_is_preserved() {
            let input = r#"
some text with spaces
```rust
fn main() {
// code inside is unchanged
}
```
more text with spaces
"#;

            let expected = r#"
some text with spaces

fn main() {
// code inside is unchanged
}

more text with spaces

"#;
            assert_eq!(render_markdown(input, false), expected);
            assert_eq!(render_markdown(input, true), expected);
        }

        #[test]
        fn rust_code_block_properties_are_passed_as_space_delimited_class() {
            let input = r#"
```rust,no_run,should_panic,property_3
```
"#;

            let expected = r#"

"#;
            assert_eq!(render_markdown(input, false), expected);
            assert_eq!(render_markdown(input, true), expected);
        }

        #[test]
        fn rust_code_block_properties_with_whitespace_are_passed_as_space_delimited_class() {
            let input = r#"
```rust,    no_run,,,should_panic , ,property_3
```
"#;

            let expected = r#"

"#;
            assert_eq!(render_markdown(input, false), expected);
            assert_eq!(render_markdown(input, true), expected);
        }

        #[test]
        fn rust_code_block_without_properties_has_proper_html_class() {
            let input = r#"
```rust
```
"#;

            let expected = r#"

"#;
            assert_eq!(render_markdown(input, false), expected);
            assert_eq!(render_markdown(input, true), expected);

            let input = r#"
```rust
```
"#;
            assert_eq!(render_markdown(input, false), expected);
            assert_eq!(render_markdown(input, true), expected);

        }
    }

    mod convert_quotes_to_curly {
        use super::super::convert_quotes_to_curly;

        #[test]
        fn it_converts_single_quotes() {
            assert_eq!(convert_quotes_to_curly("'one', 'two'"), "‘one’, ‘two’");
        }

        #[test]
        fn it_converts_double_quotes() {
            assert_eq!(convert_quotes_to_curly(r#""one", "two""#), "“one”, “two”");
        }

        #[test]
        fn it_treats_tab_as_whitespace() {
            assert_eq!(convert_quotes_to_curly("\t'one'"), "\t‘one’");
        }
    }
}
<|endoftext|>


<commit_before>extern crate term;
use std::io::timer;
use std::time::Duration;

pub fn spinner(rx: Receiver<int>, tx: Sender<int>) {
    let spinner = vec!["|", "/", "-", "\\",];
    for spin in spinner.iter().cycle() {
        say("white", "\x08");
        say("yellow", *spin);
        let r = rx.try_recv();
        match r {
            Ok(_) => {
                say("white", "\x08");
                tx.send(1);
                break;
            },
            Err(_) => {
                timer::sleep(Duration::seconds(1));
                continue;
            }
        }
    }
}

pub fn say(color: &str, to_say: &str) {
    let mut t = term::stdout().unwrap();
    let color_const = match color {
        "green" => term::color::BRIGHT_GREEN,
        "yellow" => term::color::BRIGHT_YELLOW,
        "red" => term::color::BRIGHT_RED,
        "magenta" => term::color::BRIGHT_MAGENTA,
        "white" => term::color::WHITE,
        _ => term::color::WHITE
    };
    t.fg(color_const).unwrap();
    (write!(t, "{}", to_say)).unwrap();
    t.reset().unwrap()
}

pub fn sayln(color: &str, to_say: &str) {
    let mut t = term::stdout().unwrap();
    say(color, to_say);
    (write!(t, "\n")).unwrap();
}

<commit_msg>Remove the punishing sleep<commit_after>extern crate term;
use std::io::timer;
use std::time::Duration;

pub fn spinner(rx: Receiver<int>, tx: Sender<int>) {
    let spinner = vec!["|", "/", "-", "\\",];
    for spin in spinner.iter().cycle() {
        say("white", "\x08");
        say("yellow", *spin);
        let r = rx.try_recv();
        match r {
            Ok(_) => {
                say("white", "\x08");
                tx.send(1);
                break;
            },
            Err(_) => {
                continue;
            }
        }
    }
}

pub fn say(color: &str, to_say: &str) {
    let mut t = term::stdout().unwrap();
    let color_const = match color {
        "green" => term::color::BRIGHT_GREEN,
        "yellow" => term::color::BRIGHT_YELLOW,
        "red" => term::color::BRIGHT_RED,
        "magenta" => term::color::BRIGHT_MAGENTA,
        "white" => term::color::WHITE,
        _ => term::color::WHITE
    };
    t.fg(color_const).unwrap();
    (write!(t, "{}", to_say)).unwrap();
    t.reset().unwrap()
}

pub fn sayln(color: &str, to_say: &str) {
    let mut t = term::stdout().unwrap();
    say(color, to_say);
    (write!(t, "\n")).unwrap();
}

<|endoftext|>


<commit_before>// Copyright 2019 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use exonum_merkledb::{access::Prefixed, BinaryValue, ObjectHash, Snapshot};
use failure::Error;
use futures::IntoFuture;

use std::{
    borrow::Cow,
    fmt::{self, Debug},
};

use crate::{
    crypto::{Hash, PublicKey, SecretKey},
    helpers::{Height, ValidatorId},
    messages::Verified,
    node::ApiSender,
    runtime::{
        dispatcher::{Action, Mailbox},
        AnyTx, ArtifactId, CallInfo, ExecutionError, InstanceDescriptor, InstanceId, MethodId,
    },
};

use super::{
    api::ServiceApiBuilder, ArtifactProtobufSpec, BlockchainData, CallContext, RustArtifactId,
};

/// Describes how the service instance should dispatch specific method calls
/// with consideration of the interface where the method belongs.
///
/// Usually, `ServiceDispatcher` can be derived using the
/// [`ServiceDispatcher`](index.html#examples) macro.
pub trait ServiceDispatcher: Send {
    /// Dispatches the interface method call within the specified context.
    fn call(
        &self,
        interface_name: &str,
        method: MethodId,
        ctx: CallContext<'_>,
        payload: &[u8],
    ) -> Result<(), ExecutionError>;
}

/// Describes an Exonum service instance.
///
/// That is, `Service` determines how a service instance responds to certain requests and events
/// from the runtime.
pub trait Service: ServiceDispatcher + Debug + 'static {
    /// Initializes a new service instance with the given parameters.
    ///
    /// This method is called once after creating a new service instance.
    ///
    /// The parameters passed to the method are not saved by the framework
    /// automatically, hence the user must do it manually, if needed.
    fn initialize(
        &self,
        _context: CallContext<'_>,
        _params: Vec<u8>,
    ) -> Result<(), ExecutionError> {
        Ok(())
    }

    /// Returns a list of root hashes of the Merkelized tables defined by the provided instance,
    /// based on the given snapshot of the blockchain state.
    ///
    /// The core uses this list to [aggregate][1] hashes of tables defined by every service into a
    /// single Merkelized meta-map.
    /// The hash of this meta-map is considered as the hash of the entire blockchain [state][2] and
    /// is recorded as such in blocks and Precommit messages.
    ///
    /// [See also.][3]
    ///
    /// [1]: ../struct.StateHashAggregator.html
    /// [2]: ../../blockchain/struct.Block.html#structfield.state_hash
    /// [3]: ../../blockchain/struct.Schema.html#method.state_hash_aggregator
    fn state_hash(&self, _data: BlockchainData<&dyn Snapshot>) -> Vec<Hash>;

    /// Performs storage operations on behalf of the service before committing the block.
    ///
    /// Any changes of the storage state will affect `state_hash`, which means this method must
    /// act similarly on different nodes. In other words, the service should only use data available
    /// in the provided `BeforeCommitContext`.
    ///
    /// The order of invoking the `before_commit` method is an implementation detail. Effectively,
    /// this means that services must not rely on a particular ordering of `Service::before_commit`
    /// invocations.
    fn before_commit(&self, _context: CallContext<'_>) {}

    /// Handles block commit event.
    ///
    /// This handler is an optional callback method which is invoked by the blockchain
    /// after each block commit. For example, a service can create one or more transactions
    /// if a specific condition has occurred.
    ///
    /// *Try not to perform long operations in this handler*.
    fn after_commit(&self, _context: AfterCommitContext<'_>) {}

    /// Attaches the request handlers of the service API to the Exonum API schema.
    ///
    /// The request handlers are mounted on the `/api/services/{instance_name}` path at the
    /// listen address of every full node in the blockchain network.
    fn wire_api(&self, _builder: &mut ServiceApiBuilder) {}

    // TODO: add other hooks such as "on node startup", etc. [ECR-3222]
}

/// Describes a service instance factory for the specific Rust artifact.
///
/// Usually, `ServiceFactory` can be derived using the
/// [`ServiceFactory`](index.html#examples) macro.
pub trait ServiceFactory: Send + Debug + 'static {
    /// Returns the unique artifact identifier corresponding to the factory.
    fn artifact_id(&self) -> RustArtifactId;
    /// Returns the Protobuf specification used by the instances of this service.
    fn artifact_protobuf_spec(&self) -> ArtifactProtobufSpec;
    /// Creates a new service instance.
    fn create_instance(&self) -> Box<dyn Service>;
}

impl<T> From<T> for Box<dyn ServiceFactory>
where
    T: ServiceFactory,
{
    fn from(factory: T) -> Self {
        Box::new(factory) as Self
    }
}

/// Transaction specification for a specific service interface method.
pub trait Transaction<Svc: ?Sized>: BinaryValue {
    /// Identifier of the service interface required for the call.
    #[doc(hidden)]
    const INTERFACE_NAME: &'static str;
    /// Identifier of the service method which executes the given transaction.
    const METHOD_ID: MethodId;

    /// Creates an unsigned service transaction from the value.
    fn into_any_tx(self, instance_id: InstanceId) -> AnyTx {
        AnyTx {
            call_info: CallInfo {
                instance_id,
                method_id: Self::METHOD_ID,
            },
            arguments: self.into_bytes(),
        }
    }

    /// Signs the value as a transaction with the specified instance identifier.
    fn sign(
        self,
        service_id: InstanceId,
        public_key: PublicKey,
        secret_key: &SecretKey,
    ) -> Verified<AnyTx> {
        Verified::from_value(self.into_any_tx(service_id), public_key, secret_key)
    }
}

/// Provide context for the `after_commit` handler.
pub struct AfterCommitContext<'a> {
    /// Reference to the dispatcher mailbox.
    mailbox: &'a mut Mailbox,
    /// Read-only snapshot of the current blockchain state.
    snapshot: &'a dyn Snapshot,
    /// Transaction broadcaster.
    broadcaster: Broadcaster<'a>,
    /// ID of the node as a validator.
    validator_id: Option<ValidatorId>,
}

impl<'a> AfterCommitContext<'a> {
    /// Creates a new `AfterCommit` context.
    pub(crate) fn new(
        mailbox: &'a mut Mailbox,
        instance: InstanceDescriptor<'a>,
        snapshot: &'a dyn Snapshot,
        service_keypair: &'a (PublicKey, SecretKey),
        tx_sender: &'a ApiSender,
        validator_id: Option<ValidatorId>,
    ) -> Self {
        Self {
            mailbox,
            snapshot,
            validator_id,
            broadcaster: Broadcaster::new(instance, service_keypair, tx_sender),
        }
    }

    /// Returns blockchain data for the snapshot associated with this context.
    pub fn data(&self) -> BlockchainData<&'a dyn Snapshot> {
        BlockchainData::new(self.snapshot, self.broadcaster.instance())
    }

    /// Returns snapshot of the data for the executing service.
    pub fn service_data(&self) -> Prefixed<&'a dyn Snapshot> {
        self.data().for_executing_service()
    }

    /// Returns a current blockchain height. This height is "height of the latest committed block".
    pub fn height(&self) -> Height {
        // TODO Perhaps we should optimize this method [ECR-3222]
        self.data().for_core().height()
    }

    /// Returns the service key of this node.
    pub fn service_key(&self) -> PublicKey {
        self.broadcaster.service_keypair.0
    }

    /// Returns the ID of this node as a validator. If the node is not a validator, returns `None`.
    pub fn validator_id(&self) -> Option<ValidatorId> {
        self.validator_id
    }

    /// Returns a transaction broadcaster if the current node is a validator. If the node
    /// is not a validator, returns `None`.
    pub fn broadcaster(&self) -> Option<Broadcaster<'a>> {
        self.validator_id?;
        Some(self.broadcaster.clone())
    }

    /// Returns a transaction broadcaster regardless of the node status (validator or auditor).
    pub fn generic_broadcaster(&self) -> Broadcaster<'a> {
        self.broadcaster.clone()
    }

    /// Provides a privileged interface to the supervisor service.
    ///
    /// `None` will be returned if the caller is not a supervisor.
    #[doc(hidden)]
    pub fn supervisor_extensions(&mut self) -> Option<SupervisorExtensions<'_>> {
        if !is_supervisor(self.broadcaster.instance().id) {
            return None;
        }
        Some(SupervisorExtensions {
            mailbox: &mut *self.mailbox,
        })
    }
}

// It is impossible to use `Cow` with `InstanceDescriptor` since it has a lifetime of its own.
#[derive(Debug, Clone)]
enum CowInstanceDescriptor<'a> {
    Borrowed(InstanceDescriptor<'a>),
    Owned { id: InstanceId, name: String },
}

impl CowInstanceDescriptor<'_> {
    fn as_ref(&self) -> InstanceDescriptor<'_> {
        match self {
            Self::Borrowed(descriptor) => *descriptor,
            Self::Owned { id, ref name } => InstanceDescriptor { id: *id, name },
        }
    }

    fn into_owned(self) -> CowInstanceDescriptor<'static> {
        match self {
            Self::Borrowed(InstanceDescriptor { id, name }) => CowInstanceDescriptor::Owned {
                id,
                name: name.to_owned(),
            },
            Self::Owned { id, name } => CowInstanceDescriptor::Owned { id, name },
        }
    }
}

/// Transaction broadcaster.
///
/// Transaction broadcast allows a service to create transactions in the `after_commit`
/// handler or the HTTP API handlers and broadcast them to the connected Exonum nodes.
/// The transactions are addressed to the executing service instance and are signed
/// by the [service keypair] of the node.
///
/// Broadcasting functionality is primarily useful for services that receive information
/// from outside the blockchain and need to translate it to transactions. As an example,
/// a time oracle service may broadcast local node time and build the blockchain-wide time
/// by processing corresponding transactions.
///
/// [service keypair]: ../../blockchain/config/struct.ValidatorKeys.html#structfield.service_key
#[derive(Debug, Clone)]
pub struct Broadcaster<'a> {
    instance: CowInstanceDescriptor<'a>,
    service_keypair: Cow<'a, (PublicKey, SecretKey)>,
    tx_sender: Cow<'a, ApiSender>,
}

impl<'a> Broadcaster<'a> {
    /// Creates a new broadcaster.
    pub(super) fn new(
        instance: InstanceDescriptor<'a>,
        service_keypair: &'a (PublicKey, SecretKey),
        tx_sender: &'a ApiSender,
    ) -> Self {
        Self {
            instance: CowInstanceDescriptor::Borrowed(instance),
            service_keypair: Cow::Borrowed(service_keypair),
            tx_sender: Cow::Borrowed(tx_sender),
        }
    }

    pub(super) fn keypair(&self) -> &(PublicKey, SecretKey) {
        self.service_keypair.as_ref()
    }

    pub(super) fn instance(&self) -> InstanceDescriptor<'_> {
        self.instance.as_ref()
    }

    /// Signs and broadcasts a transaction to the other nodes in the network.
    ///
    /// The transaction is signed by the service keypair of the node. The same input transaction
    /// will lead to the identical transaction being broadcast. If this is undesired, add a nonce
    /// field to the input transaction (e.g., a `u64`) and change it between the calls.
    ///
    /// # Return value
    ///
    /// Returns the hash of the created transaction, or an error if the transaction cannot be
    /// broadcast. An error means that the node is being shut down.
    pub fn send<Svc: ?Sized, T>(self, tx: T) -> Result<Hash, Error>
    where
        T: Transaction<Svc>,
    {
        let (public_key, secret_key) = self.service_keypair.as_ref();
        let msg = tx.sign(self.instance().id, *public_key, secret_key);
        let tx_hash = msg.object_hash();
        self.tx_sender.broadcast_transaction(msg).map(|()| tx_hash)
    }

    /// Converts the broadcaster into the owned representation, which can be used to broadcast
    /// transactions asynchronously.
    pub fn into_owned(self) -> Broadcaster<'static> {
        Broadcaster {
            instance: self.instance.into_owned(),
            service_keypair: Cow::Owned(self.service_keypair.into_owned()),
            tx_sender: Cow::Owned(self.tx_sender.into_owned()),
        }
    }
}

/// Extended blockchain interface for the service instance authorized as a supervisor.
#[derive(Debug)]
pub struct SupervisorExtensions<'a> {
    mailbox: &'a mut Mailbox,
}

impl SupervisorExtensions<'_> {
    /// Starts the deployment of an artifact. The provided callback is executed after
    /// the deployment is completed.
    pub fn start_deploy<F>(
        &mut self,
        artifact: ArtifactId,
        spec: impl BinaryValue,
        and_then: impl FnOnce() -> F + 'static + Send,
    ) where
        F: IntoFuture<Item = (), Error = ExecutionError>,
        F::Future: 'static + Send,
    {
        let action = Action::StartDeploy {
            artifact,
            spec: spec.into_bytes(),
            and_then: Box::new(|| Box::new(and_then().into_future())),
        };
        self.mailbox.push(action);
    }
}

impl Debug for AfterCommitContext<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("AfterCommitContext")
            .field("instance", &self.broadcaster.instance)
            .finish()
    }
}

/// A service interface specification.
pub trait Interface {
    /// Fully qualified name of this interface.
    const INTERFACE_NAME: &'static str;
    /// Invokes the specified method handler of the service instance.
    fn dispatch(
        &self,
        context: CallContext<'_>,
        method: MethodId,
        payload: &[u8],
    ) -> Result<(), ExecutionError>;
}

fn is_supervisor(instance_id: InstanceId) -> bool {
    instance_id == crate::runtime::SUPERVISOR_INSTANCE_ID
}
<commit_msg>Restore 1.36 compatibility (#1586)<commit_after>// Copyright 2019 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use exonum_merkledb::{access::Prefixed, BinaryValue, ObjectHash, Snapshot};
use failure::Error;
use futures::IntoFuture;

use std::{
    borrow::Cow,
    fmt::{self, Debug},
};

use crate::{
    crypto::{Hash, PublicKey, SecretKey},
    helpers::{Height, ValidatorId},
    messages::Verified,
    node::ApiSender,
    runtime::{
        dispatcher::{Action, Mailbox},
        AnyTx, ArtifactId, CallInfo, ExecutionError, InstanceDescriptor, InstanceId, MethodId,
    },
};

use super::{
    api::ServiceApiBuilder, ArtifactProtobufSpec, BlockchainData, CallContext, RustArtifactId,
};

/// Describes how the service instance should dispatch specific method calls
/// with consideration of the interface where the method belongs.
///
/// Usually, `ServiceDispatcher` can be derived using the
/// [`ServiceDispatcher`](index.html#examples) macro.
pub trait ServiceDispatcher: Send {
    /// Dispatches the interface method call within the specified context.
    fn call(
        &self,
        interface_name: &str,
        method: MethodId,
        ctx: CallContext<'_>,
        payload: &[u8],
    ) -> Result<(), ExecutionError>;
}

/// Describes an Exonum service instance.
///
/// That is, `Service` determines how a service instance responds to certain requests and events
/// from the runtime.
pub trait Service: ServiceDispatcher + Debug + 'static {
    /// Initializes a new service instance with the given parameters.
    ///
    /// This method is called once after creating a new service instance.
    ///
    /// The parameters passed to the method are not saved by the framework
    /// automatically, hence the user must do it manually, if needed.
    fn initialize(
        &self,
        _context: CallContext<'_>,
        _params: Vec<u8>,
    ) -> Result<(), ExecutionError> {
        Ok(())
    }

    /// Returns a list of root hashes of the Merkelized tables defined by the provided instance,
    /// based on the given snapshot of the blockchain state.
    ///
    /// The core uses this list to [aggregate][1] hashes of tables defined by every service into a
    /// single Merkelized meta-map.
    /// The hash of this meta-map is considered as the hash of the entire blockchain [state][2] and
    /// is recorded as such in blocks and Precommit messages.
    ///
    /// [See also.][3]
    ///
    /// [1]: ../struct.StateHashAggregator.html
    /// [2]: ../../blockchain/struct.Block.html#structfield.state_hash
    /// [3]: ../../blockchain/struct.Schema.html#method.state_hash_aggregator
    fn state_hash(&self, _data: BlockchainData<&dyn Snapshot>) -> Vec<Hash>;

    /// Performs storage operations on behalf of the service before committing the block.
    ///
    /// Any changes of the storage state will affect `state_hash`, which means this method must
    /// act similarly on different nodes. In other words, the service should only use data available
    /// in the provided `BeforeCommitContext`.
    ///
    /// The order of invoking the `before_commit` method is an implementation detail. Effectively,
    /// this means that services must not rely on a particular ordering of `Service::before_commit`
    /// invocations.
    fn before_commit(&self, _context: CallContext<'_>) {}

    /// Handles block commit event.
    ///
    /// This handler is an optional callback method which is invoked by the blockchain
    /// after each block commit. For example, a service can create one or more transactions
    /// if a specific condition has occurred.
    ///
    /// *Try not to perform long operations in this handler*.
    fn after_commit(&self, _context: AfterCommitContext<'_>) {}

    /// Attaches the request handlers of the service API to the Exonum API schema.
    ///
    /// The request handlers are mounted on the `/api/services/{instance_name}` path at the
    /// listen address of every full node in the blockchain network.
    fn wire_api(&self, _builder: &mut ServiceApiBuilder) {}

    // TODO: add other hooks such as "on node startup", etc. [ECR-3222]
}

/// Describes a service instance factory for the specific Rust artifact.
///
/// Usually, `ServiceFactory` can be derived using the
/// [`ServiceFactory`](index.html#examples) macro.
pub trait ServiceFactory: Send + Debug + 'static {
    /// Returns the unique artifact identifier corresponding to the factory.
    fn artifact_id(&self) -> RustArtifactId;
    /// Returns the Protobuf specification used by the instances of this service.
    fn artifact_protobuf_spec(&self) -> ArtifactProtobufSpec;
    /// Creates a new service instance.
    fn create_instance(&self) -> Box<dyn Service>;
}

impl<T> From<T> for Box<dyn ServiceFactory>
where
    T: ServiceFactory,
{
    fn from(factory: T) -> Self {
        Box::new(factory) as Self
    }
}

/// Transaction specification for a specific service interface method.
pub trait Transaction<Svc: ?Sized>: BinaryValue {
    /// Identifier of the service interface required for the call.
    #[doc(hidden)]
    const INTERFACE_NAME: &'static str;
    /// Identifier of the service method which executes the given transaction.
    const METHOD_ID: MethodId;

    /// Creates an unsigned service transaction from the value.
    fn into_any_tx(self, instance_id: InstanceId) -> AnyTx {
        AnyTx {
            call_info: CallInfo {
                instance_id,
                method_id: Self::METHOD_ID,
            },
            arguments: self.into_bytes(),
        }
    }

    /// Signs the value as a transaction with the specified instance identifier.
    fn sign(
        self,
        service_id: InstanceId,
        public_key: PublicKey,
        secret_key: &SecretKey,
    ) -> Verified<AnyTx> {
        Verified::from_value(self.into_any_tx(service_id), public_key, secret_key)
    }
}

/// Provide context for the `after_commit` handler.
pub struct AfterCommitContext<'a> {
    /// Reference to the dispatcher mailbox.
    mailbox: &'a mut Mailbox,
    /// Read-only snapshot of the current blockchain state.
    snapshot: &'a dyn Snapshot,
    /// Transaction broadcaster.
    broadcaster: Broadcaster<'a>,
    /// ID of the node as a validator.
    validator_id: Option<ValidatorId>,
}

impl<'a> AfterCommitContext<'a> {
    /// Creates a new `AfterCommit` context.
    pub(crate) fn new(
        mailbox: &'a mut Mailbox,
        instance: InstanceDescriptor<'a>,
        snapshot: &'a dyn Snapshot,
        service_keypair: &'a (PublicKey, SecretKey),
        tx_sender: &'a ApiSender,
        validator_id: Option<ValidatorId>,
    ) -> Self {
        Self {
            mailbox,
            snapshot,
            validator_id,
            broadcaster: Broadcaster::new(instance, service_keypair, tx_sender),
        }
    }

    /// Returns blockchain data for the snapshot associated with this context.
    pub fn data(&self) -> BlockchainData<&'a dyn Snapshot> {
        BlockchainData::new(self.snapshot, self.broadcaster.instance())
    }

    /// Returns snapshot of the data for the executing service.
    pub fn service_data(&self) -> Prefixed<&'a dyn Snapshot> {
        self.data().for_executing_service()
    }

    /// Returns a current blockchain height. This height is "height of the latest committed block".
    pub fn height(&self) -> Height {
        // TODO Perhaps we should optimize this method [ECR-3222]
        self.data().for_core().height()
    }

    /// Returns the service key of this node.
    pub fn service_key(&self) -> PublicKey {
        self.broadcaster.service_keypair.0
    }

    /// Returns the ID of this node as a validator. If the node is not a validator, returns `None`.
    pub fn validator_id(&self) -> Option<ValidatorId> {
        self.validator_id
    }

    /// Returns a transaction broadcaster if the current node is a validator. If the node
    /// is not a validator, returns `None`.
    pub fn broadcaster(&self) -> Option<Broadcaster<'a>> {
        self.validator_id?;
        Some(self.broadcaster.clone())
    }

    /// Returns a transaction broadcaster regardless of the node status (validator or auditor).
    pub fn generic_broadcaster(&self) -> Broadcaster<'a> {
        self.broadcaster.clone()
    }

    /// Provides a privileged interface to the supervisor service.
    ///
    /// `None` will be returned if the caller is not a supervisor.
    #[doc(hidden)]
    pub fn supervisor_extensions(&mut self) -> Option<SupervisorExtensions<'_>> {
        if !is_supervisor(self.broadcaster.instance().id) {
            return None;
        }
        Some(SupervisorExtensions {
            mailbox: &mut *self.mailbox,
        })
    }
}

// It is impossible to use `Cow` with `InstanceDescriptor` since it has a lifetime of its own.
#[derive(Debug, Clone)]
enum CowInstanceDescriptor<'a> {
    Borrowed(InstanceDescriptor<'a>),
    Owned { id: InstanceId, name: String },
}

impl CowInstanceDescriptor<'_> {
    fn as_ref(&self) -> InstanceDescriptor<'_> {
        match self {
            CowInstanceDescriptor::Borrowed(descriptor) => *descriptor,
            CowInstanceDescriptor::Owned { id, ref name } => InstanceDescriptor { id: *id, name },
        }
    }

    fn into_owned(self) -> CowInstanceDescriptor<'static> {
        match self {
            CowInstanceDescriptor::Borrowed(InstanceDescriptor { id, name }) => {
                CowInstanceDescriptor::Owned {
                    id,
                    name: name.to_owned(),
                }
            }
            CowInstanceDescriptor::Owned { id, name } => CowInstanceDescriptor::Owned { id, name },
        }
    }
}

/// Transaction broadcaster.
///
/// Transaction broadcast allows a service to create transactions in the `after_commit`
/// handler or the HTTP API handlers and broadcast them to the connected Exonum nodes.
/// The transactions are addressed to the executing service instance and are signed
/// by the [service keypair] of the node.
///
/// Broadcasting functionality is primarily useful for services that receive information
/// from outside the blockchain and need to translate it to transactions. As an example,
/// a time oracle service may broadcast local node time and build the blockchain-wide time
/// by processing corresponding transactions.
///
/// [service keypair]: ../../blockchain/config/struct.ValidatorKeys.html#structfield.service_key
#[derive(Debug, Clone)]
pub struct Broadcaster<'a> {
    instance: CowInstanceDescriptor<'a>,
    service_keypair: Cow<'a, (PublicKey, SecretKey)>,
    tx_sender: Cow<'a, ApiSender>,
}

impl<'a> Broadcaster<'a> {
    /// Creates a new broadcaster.
    pub(super) fn new(
        instance: InstanceDescriptor<'a>,
        service_keypair: &'a (PublicKey, SecretKey),
        tx_sender: &'a ApiSender,
    ) -> Self {
        Self {
            instance: CowInstanceDescriptor::Borrowed(instance),
            service_keypair: Cow::Borrowed(service_keypair),
            tx_sender: Cow::Borrowed(tx_sender),
        }
    }

    pub(super) fn keypair(&self) -> &(PublicKey, SecretKey) {
        self.service_keypair.as_ref()
    }

    pub(super) fn instance(&self) -> InstanceDescriptor<'_> {
        self.instance.as_ref()
    }

    /// Signs and broadcasts a transaction to the other nodes in the network.
    ///
    /// The transaction is signed by the service keypair of the node. The same input transaction
    /// will lead to the identical transaction being broadcast. If this is undesired, add a nonce
    /// field to the input transaction (e.g., a `u64`) and change it between the calls.
    ///
    /// # Return value
    ///
    /// Returns the hash of the created transaction, or an error if the transaction cannot be
    /// broadcast. An error means that the node is being shut down.
    pub fn send<Svc: ?Sized, T>(self, tx: T) -> Result<Hash, Error>
    where
        T: Transaction<Svc>,
    {
        let (public_key, secret_key) = self.service_keypair.as_ref();
        let msg = tx.sign(self.instance().id, *public_key, secret_key);
        let tx_hash = msg.object_hash();
        self.tx_sender.broadcast_transaction(msg).map(|()| tx_hash)
    }

    /// Converts the broadcaster into the owned representation, which can be used to broadcast
    /// transactions asynchronously.
    pub fn into_owned(self) -> Broadcaster<'static> {
        Broadcaster {
            instance: self.instance.into_owned(),
            service_keypair: Cow::Owned(self.service_keypair.into_owned()),
            tx_sender: Cow::Owned(self.tx_sender.into_owned()),
        }
    }
}

/// Extended blockchain interface for the service instance authorized as a supervisor.
#[derive(Debug)]
pub struct SupervisorExtensions<'a> {
    mailbox: &'a mut Mailbox,
}

impl SupervisorExtensions<'_> {
    /// Starts the deployment of an artifact. The provided callback is executed after
    /// the deployment is completed.
    pub fn start_deploy<F>(
        &mut self,
        artifact: ArtifactId,
        spec: impl BinaryValue,
        and_then: impl FnOnce() -> F + 'static + Send,
    ) where
        F: IntoFuture<Item = (), Error = ExecutionError>,
        F::Future: 'static + Send,
    {
        let action = Action::StartDeploy {
            artifact,
            spec: spec.into_bytes(),
            and_then: Box::new(|| Box::new(and_then().into_future())),
        };
        self.mailbox.push(action);
    }
}

impl Debug for AfterCommitContext<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("AfterCommitContext")
            .field("instance", &self.broadcaster.instance)
            .finish()
    }
}

/// A service interface specification.
pub trait Interface {
    /// Fully qualified name of this interface.
    const INTERFACE_NAME: &'static str;
    /// Invokes the specified method handler of the service instance.
    fn dispatch(
        &self,
        context: CallContext<'_>,
        method: MethodId,
        payload: &[u8],
    ) -> Result<(), ExecutionError>;
}

fn is_supervisor(instance_id: InstanceId) -> bool {
    instance_id == crate::runtime::SUPERVISOR_INSTANCE_ID
}
<|endoftext|>


<commit_before>//! Xml Attributes module
//!
//! Provides an iterator over attributes key/value pairs
use std::borrow::Cow;
use std::ops::Range;
use std::io::BufRead;
use errors::{Error, Result};
use escape::{escape, unescape};
use reader::{is_whitespace, Reader};

/// Iterator over attributes key/value pairs
#[derive(Clone)]
pub struct Attributes<'a> {
    /// slice of `Element` corresponding to attributes
    bytes: &'a [u8],
    /// current position of the iterator
    position: usize,
    /// if true, checks for duplicate names
    with_checks: bool,
    /// allows attribute without quote or `=`
    html: bool,
    /// if `with_checks`, contains the ranges corresponding to the
    /// attribute names already parsed in this `Element`
    consumed: Vec<Range<usize>>,
}

impl<'a> Attributes<'a> {
    /// creates a new attribute iterator from a buffer
    pub fn new(buf: &'a [u8], pos: usize) -> Attributes<'a> {
        Attributes {
            bytes: buf,
            position: pos,
            html: false,
            with_checks: true,
            consumed: Vec::new(),
        }
    }

    /// creates a new attribute iterator from a buffer, allowing html attribute syntax
    pub fn html(buf: &'a [u8], pos: usize) -> Attributes<'a> {
        Attributes {
            bytes: buf,
            position: pos,
            html: true,
            with_checks: true,
            consumed: Vec::new(),
        }
    }

    /// check if attributes are distincts
    pub fn with_checks(&mut self, val: bool) -> &mut Attributes<'a> {
        self.with_checks = val;
        self
    }

    /// allow attributes without quote or `=`
    pub fn html_style(&mut self, val: bool) -> &mut Attributes<'a> {
        self.html = val;
        self
    }

    /// sets `self.exit = true` to terminate the iterator
    fn error(&mut self, err: Error, len: usize) -> Result<Attribute<'a>> {
        self.position = len;
        Err(err.into())
    }
}

/// A struct representing a key/value for a xml attribute
///
/// Parses either `key="value"` or `key='value'`.
/// Field `value` stores raw bytes, possibly containing escape-sequences.
#[derive(Debug, Clone, PartialEq)]
pub struct Attribute<'a> {
    /// the key to uniquely define the attribute
    pub key: &'a [u8],
    /// the raw value of attribute
    pub value: Cow<'a, [u8]>,
}

impl<'a> Attribute<'a> {
    /// unescapes the value
    pub fn unescaped_value(&self) -> Result<Cow<[u8]>> {
        unescape(&*self.value).map_err(Error::EscapeError)
    }

    /// unescapes then decode the value
    ///
    /// for performance reasons (could avoid allocating a `String`),
    /// it might be wiser to manually use
    /// 1. Attributes::unescaped_value()
    /// 2. Reader::decode(...)
    pub fn unescape_and_decode_value<B: BufRead>(&self, reader: &Reader<B>) -> Result<String> {
        self.unescaped_value()
            .map(|e| reader.decode(&*e).into_owned())
    }
}

impl<'a> From<(&'a [u8], &'a [u8])> for Attribute<'a> {
    /// Creates new attribute from raw bytes.
    /// Does not apply any transformation to both key and value.
    ///
    /// # Example
    /// ```
    /// use quick_xml::events::attributes::Attribute;
    ///
    /// let features = Attribute::from(("features".as_bytes(), "Bells & whistles".as_bytes()));
    /// assert_eq!(features.value, "Bells & whistles".as_bytes());
    /// ```
    fn from(val: (&'a [u8], &'a [u8])) -> Attribute<'a> {
        Attribute {
            key: val.0,
            value: Cow::from(val.1),
        }
    }
}

impl<'a> From<(&'a str, &'a str)> for Attribute<'a> {
    /// Creates new attribute from text representation.
    /// Key is stored as-is, but the value will be escaped.
    ///
    /// # Example
    /// ```
    /// use quick_xml::events::attributes::Attribute;
    ///
    /// let features = Attribute::from(("features", "Bells & whistles"));
    /// assert_eq!(features.value, "Bells & whistles".as_bytes());
    /// ```
    fn from(val: (&'a str, &'a str)) -> Attribute<'a> {
        Attribute {
            key: val.0.as_bytes(),
            value: escape(val.1.as_bytes()),
        }
    }
}

impl<'a> Iterator for Attributes<'a> {
    type Item = Result<Attribute<'a>>;
    fn next(&mut self) -> Option<Self::Item> {

        let len = self.bytes.len();

        // helper macro for last attribute
        macro_rules! attr {
            ($key: expr) => {
                {
                    self.position = len;
                    if self.html {
                        attr!($key, 0..0)
                    } else {
                        return None;
                    };
                }
            };
            ($key:expr, $val: expr) => {
                return Some(Ok(Attribute {
                    key: &self.bytes[$key],
                    value: Cow::Borrowed(&self.bytes[$val]),
                }));
            };
        }

        if len <= self.position {
            return None;
        }

        let mut bytes = self.bytes.iter().enumerate().skip(self.position);

        // key starts after the whitespace
        let start_key = match bytes.by_ref()
            .skip_while(|&(_, &b)| !is_whitespace(b))
            .find(|&(_, &b)| !is_whitespace(b)) {
            Some((i, _)) => i,
            None => attr!(self.position..len),
        };

        // key ends with either whitespace or =
        let end_key = match bytes.by_ref().find(|&(_, &b)| b == b'=' || is_whitespace(b)) {
            Some((i, &b'=')) => i,
            Some((i, &b'\'')) | Some((i, &b'"')) if self.with_checks => {
                return Some(self.error(Error::NameWithQuote(i), len));
            }
            Some((i, _)) => {
                // consume until `=` or return if html
                match bytes.by_ref().find(|&(_, &b)| !is_whitespace(b)) {
                    Some((_, &b'=')) => i,
                    Some((j, _)) => {
                        if self.html {
                            self.position = j - 1;
                            attr!(start_key..i, 0..0);
                        }
                        return Some(self.error(Error::NoEqAfterName(j), len));
                    }
                    None if self.html => {
                        self.position = len;
                        attr!(start_key..len, 0..0);
                    }
                    None => return Some(self.error(Error::NoEqAfterName(len), len)),
                }
            }
            None => attr!(start_key..len),
        };

        if self.with_checks {
            if let Some(start) = self.consumed
                .iter()
                .filter(|r| r.len() == end_key - start_key)
                .find(|r| &self.bytes[(*r).clone()] == &self.bytes[start_key..end_key])
                .map(|ref r| r.start)
            {
                return Some(self.error(Error::DuplicatedAttribute(start_key, start), len));
            }
            self.consumed.push(start_key..end_key);
        }

        // value has quote if not html
        match bytes.by_ref().find(|&(_, &b)| !is_whitespace(b)) {
            Some((i, quote @ &b'\'')) | Some((i, quote @ &b'"')) => {
                match bytes.by_ref().find(|&(_, &b)| b == *quote) {
                    Some((j, _)) => {
                        self.position = j + 1;
                        attr!(start_key..end_key, i + 1..j)
                    }
                    None => Some(self.error(Error::UnquotedValue(i), len)),
                }
            },
            Some((i, _)) if self.html => {
                let j = bytes.by_ref().find(|&(_, &b)| is_whitespace(b)).map_or(len, |(j, _)| j);
                self.position = j;
                attr!(start_key..end_key, i..j)
            }
            Some((i, _)) => Some(self.error(Error::UnquotedValue(i), len)),
            None => attr!(start_key..end_key),
        }
    }
}

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

    #[test]
    fn regular() {
        let event = b"name a='a' b = 'b'";
        let mut attributes = Attributes::new(event, 0);
        attributes.with_checks(true);
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"a");
        assert_eq!(&*a.value, b"a");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"b");
        assert_eq!(&*a.value, b"b");
        assert!(attributes.next().is_none());
    }

    #[test]
    fn mixed_quote() {
        let event = b"name a='a' b = \"b\" c='cc\"cc'";
        let mut attributes = Attributes::new(event, 0);
        attributes.with_checks(true);
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"a");
        assert_eq!(&*a.value, b"a");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"b");
        assert_eq!(&*a.value, b"b");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"c");
        assert_eq!(&*a.value, b"cc\"cc");
        assert!(attributes.next().is_none());
    }

    #[test]
    fn html_fail() {
        let event = b"name a='a' b=b c";
        let mut attributes = Attributes::new(event, 0);
        attributes.with_checks(true);
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"a");
        assert_eq!(&*a.value, b"a");
        assert!(attributes.next().unwrap().is_err());
    }

    #[test]
    fn html_ok() {
        let event = b"name a='a' e b=b c d ee=ee";
        let mut attributes = Attributes::new(event, 0);
        attributes.with_checks(true).html_style(true);
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"a");
        assert_eq!(&*a.value, b"a");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"e");
        assert_eq!(&*a.value, b"");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"b");
        assert_eq!(&*a.value, b"b");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"c");
        assert_eq!(&*a.value, b"");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"d");
        assert_eq!(&*a.value, b"");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"ee");
        assert_eq!(&*a.value, b"ee");
        assert!(attributes.next().is_none());
    }
}
<commit_msg>clean code<commit_after>//! Xml Attributes module
//!
//! Provides an iterator over attributes key/value pairs
use std::borrow::Cow;
use std::ops::Range;
use std::io::BufRead;
use errors::{Error, Result};
use escape::{escape, unescape};
use reader::{is_whitespace, Reader};

/// Iterator over attributes key/value pairs
#[derive(Clone)]
pub struct Attributes<'a> {
    /// slice of `Element` corresponding to attributes
    bytes: &'a [u8],
    /// current position of the iterator
    position: usize,
    /// if true, checks for duplicate names
    with_checks: bool,
    /// allows attribute without quote or `=`
    html: bool,
    /// if `with_checks`, contains the ranges corresponding to the
    /// attribute names already parsed in this `Element`
    consumed: Vec<Range<usize>>,
}

impl<'a> Attributes<'a> {
    /// creates a new attribute iterator from a buffer
    pub fn new(buf: &'a [u8], pos: usize) -> Attributes<'a> {
        Attributes {
            bytes: buf,
            position: pos,
            html: false,
            with_checks: true,
            consumed: Vec::new(),
        }
    }

    /// creates a new attribute iterator from a buffer, allowing html attribute syntax
    pub fn html(buf: &'a [u8], pos: usize) -> Attributes<'a> {
        Attributes {
            bytes: buf,
            position: pos,
            html: true,
            with_checks: true,
            consumed: Vec::new(),
        }
    }

    /// check if attributes are distincts
    pub fn with_checks(&mut self, val: bool) -> &mut Attributes<'a> {
        self.with_checks = val;
        self
    }
}

/// A struct representing a key/value for a xml attribute
///
/// Parses either `key="value"` or `key='value'`.
/// Field `value` stores raw bytes, possibly containing escape-sequences.
#[derive(Debug, Clone, PartialEq)]
pub struct Attribute<'a> {
    /// the key to uniquely define the attribute
    pub key: &'a [u8],
    /// the raw value of attribute
    pub value: Cow<'a, [u8]>,
}

impl<'a> Attribute<'a> {
    /// unescapes the value
    pub fn unescaped_value(&self) -> Result<Cow<[u8]>> {
        unescape(&*self.value).map_err(Error::EscapeError)
    }

    /// unescapes then decode the value
    ///
    /// for performance reasons (could avoid allocating a `String`),
    /// it might be wiser to manually use
    /// 1. Attributes::unescaped_value()
    /// 2. Reader::decode(...)
    pub fn unescape_and_decode_value<B: BufRead>(&self, reader: &Reader<B>) -> Result<String> {
        self.unescaped_value()
            .map(|e| reader.decode(&*e).into_owned())
    }
}

impl<'a> From<(&'a [u8], &'a [u8])> for Attribute<'a> {
    /// Creates new attribute from raw bytes.
    /// Does not apply any transformation to both key and value.
    ///
    /// # Example
    /// ```
    /// use quick_xml::events::attributes::Attribute;
    ///
    /// let features = Attribute::from(("features".as_bytes(), "Bells & whistles".as_bytes()));
    /// assert_eq!(features.value, "Bells & whistles".as_bytes());
    /// ```
    fn from(val: (&'a [u8], &'a [u8])) -> Attribute<'a> {
        Attribute {
            key: val.0,
            value: Cow::from(val.1),
        }
    }
}

impl<'a> From<(&'a str, &'a str)> for Attribute<'a> {
    /// Creates new attribute from text representation.
    /// Key is stored as-is, but the value will be escaped.
    ///
    /// # Example
    /// ```
    /// use quick_xml::events::attributes::Attribute;
    ///
    /// let features = Attribute::from(("features", "Bells & whistles"));
    /// assert_eq!(features.value, "Bells & whistles".as_bytes());
    /// ```
    fn from(val: (&'a str, &'a str)) -> Attribute<'a> {
        Attribute {
            key: val.0.as_bytes(),
            value: escape(val.1.as_bytes()),
        }
    }
}

impl<'a> Iterator for Attributes<'a> {
    type Item = Result<Attribute<'a>>;
    fn next(&mut self) -> Option<Self::Item> {

        let len = self.bytes.len();

        macro_rules! err {
            ($err: expr) => {{
                self.position = len;
                return Some(Err($err.into()));
            }}
        }

        macro_rules! attr {
            ($key: expr) => {{
                self.position = len;
                if self.html {
                    attr!($key, 0..0)
                } else {
                    return None;
                };
            }};
            ($key:expr, $val: expr) => {
                return Some(Ok(Attribute {
                    key: &self.bytes[$key],
                    value: Cow::Borrowed(&self.bytes[$val]),
                }));
            };
        }

        if len <= self.position {
            return None;
        }

        let mut bytes = self.bytes.iter().enumerate().skip(self.position);

        // key starts after the whitespace
        let start_key = match bytes.by_ref()
            .skip_while(|&(_, &b)| !is_whitespace(b))
            .find(|&(_, &b)| !is_whitespace(b)) {
            Some((i, _)) => i,
            None => attr!(self.position..len),
        };

        // key ends with either whitespace or =
        let end_key = match bytes.by_ref().find(|&(_, &b)| b == b'=' || is_whitespace(b)) {
            Some((i, &b'=')) => i,
            Some((i, &b'\'')) | Some((i, &b'"')) if self.with_checks => {
                err!(Error::NameWithQuote(i));
            }
            Some((i, _)) => {
                // consume until `=` or return if html
                match bytes.by_ref().find(|&(_, &b)| !is_whitespace(b)) {
                    Some((_, &b'=')) => i,
                    Some((j, _)) if self.html => {
                        self.position = j - 1;
                        attr!(start_key..i, 0..0);
                    }
                    Some((j, _)) => err!(Error::NoEqAfterName(j)),
                    None if self.html => {
                        self.position = len;
                        attr!(start_key..len, 0..0);
                    }
                    None => err!(Error::NoEqAfterName(len)),
                }
            }
            None => attr!(start_key..len),
        };

        if self.with_checks {
            if let Some(start) = self.consumed
                .iter()
                .filter(|r| r.len() == end_key - start_key)
                .find(|r| &self.bytes[(*r).clone()] == &self.bytes[start_key..end_key])
                .map(|ref r| r.start)
            {
                err!(Error::DuplicatedAttribute(start_key, start));
            }
            self.consumed.push(start_key..end_key);
        }

        // value has quote if not html
        match bytes.by_ref().find(|&(_, &b)| !is_whitespace(b)) {
            Some((i, quote @ &b'\'')) | Some((i, quote @ &b'"')) => {
                match bytes.by_ref().find(|&(_, &b)| b == *quote) {
                    Some((j, _)) => {
                        self.position = j + 1;
                        attr!(start_key..end_key, i + 1..j)
                    }
                    None => err!(Error::UnquotedValue(i)),
                }
            },
            Some((i, _)) if self.html => {
                let j = bytes.by_ref().find(|&(_, &b)| is_whitespace(b)).map_or(len, |(j, _)| j);
                self.position = j;
                attr!(start_key..end_key, i..j)
            }
            Some((i, _)) => err!(Error::UnquotedValue(i)),
            None => attr!(start_key..end_key),
        }
    }
}

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

    #[test]
    fn regular() {
        let event = b"name a='a' b = 'b'";
        let mut attributes = Attributes::new(event, 0);
        attributes.with_checks(true);
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"a");
        assert_eq!(&*a.value, b"a");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"b");
        assert_eq!(&*a.value, b"b");
        assert!(attributes.next().is_none());
    }

    #[test]
    fn mixed_quote() {
        let event = b"name a='a' b = \"b\" c='cc\"cc'";
        let mut attributes = Attributes::new(event, 0);
        attributes.with_checks(true);
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"a");
        assert_eq!(&*a.value, b"a");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"b");
        assert_eq!(&*a.value, b"b");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"c");
        assert_eq!(&*a.value, b"cc\"cc");
        assert!(attributes.next().is_none());
    }

    #[test]
    fn html_fail() {
        let event = b"name a='a' b=b c";
        let mut attributes = Attributes::new(event, 0);
        attributes.with_checks(true);
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"a");
        assert_eq!(&*a.value, b"a");
        assert!(attributes.next().unwrap().is_err());
    }

    #[test]
    fn html_ok() {
        let event = b"name a='a' e b=b c d ee=ee";
        let mut attributes = Attributes::html(event, 0);
        attributes.with_checks(true);
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"a");
        assert_eq!(&*a.value, b"a");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"e");
        assert_eq!(&*a.value, b"");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"b");
        assert_eq!(&*a.value, b"b");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"c");
        assert_eq!(&*a.value, b"");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"d");
        assert_eq!(&*a.value, b"");
        let a = attributes.next().unwrap().unwrap();
        assert_eq!(a.key, b"ee");
        assert_eq!(&*a.value, b"ee");
        assert!(attributes.next().is_none());
    }
}
<|endoftext|>


<commit_before>use super::camera::*;
use super::event_manager::*;
use glium::backend::glutin_backend::GlutinFacade;
use glium::glutin::{CursorState, ElementState, Event, MouseButton, VirtualKeyCode};

pub struct Ghost {
    cam: Camera,
    prev_mouse_pos: Option<(i32, i32)>,
    context: GlutinFacade,
}

impl Ghost {
    pub fn new(context: GlutinFacade) -> Self {
        Ghost {
            cam: Camera::default(),
            prev_mouse_pos: None,
            context: context,
        }
    }

    pub fn get_camera(&self) -> Camera {
        self.cam
    }
}

/// **Implements Controls**
/// *W => FORWARD
/// *A => LEFT
/// *S => BACKWARDS
/// *D => RIGHT
/// *'Space' => UP
/// *'LControl' => DOWN (only accepts one keystroke (cannot hold LControl to go
/// down))
/// *'C' => DOWN (as a replacement for 'LControl')

/// MouseMovement for changing the direction the camera looks
impl EventHandler for Ghost {
    fn handle_event(&mut self, e: &Event) -> EventResponse {
        match *e {
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::W)) => {
                self.cam.move_forward(1.0);
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::S)) => {
                self.cam.move_backward(1.0);
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::A)) => {
                self.cam.move_left(1.0);
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::D)) => {
                self.cam.move_right(1.0);
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::Space)) => {
                self.cam.move_up(1.0);
                EventResponse::Continue
            }
            // X only for the fact, that you cannot hold LControl to go down,
            // because holding the key only counts as one keystroke
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::C)) => {
                self.cam.move_down(1.0);
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::LControl)) => {
                self.cam.move_down(1.0);
                EventResponse::Continue
            }

            Event::MouseInput(ElementState::Pressed, MouseButton::Left) => {
                info!("clicked");
                if let Some(window) = self.context.get_window() {
                    let res = window.set_cursor_state(CursorState::Hide);
                    warn!("{:?}", res);
                } else {
                    warn!("Failed to obtain window from facade");
                }
                EventResponse::Continue
            }
            Event::MouseMoved(x, y) => {

                if let Some((prev_x, prev_y)) = self.prev_mouse_pos {
                    let x_diff = x - prev_x;
                    let y_diff = y - prev_y;
                    info!("x = {}, y = {}", x_diff, y_diff);
                    self.cam.change_dir(y_diff as f32 / 300.0, -x_diff as f32 / 300.0);
                }

                self.prev_mouse_pos = Some((x, y));

                EventResponse::Continue
            }
            // Event::MouseMoved(x, y) => {
            //     if let Some(window) = self.context.get_window() {
            //         // Possibility of mouse being outside of window without it reseting to the
            //         // middle?
            //         if let Some(middle) = window.get_inner_size_pixels() {
            //             let middle_x = (middle.0 as i32) / 2;
            //             let middle_y = (middle.1 as i32) / 2;
            //             let x_diff = x - middle_x;
            //             let y_diff = y - middle_y;
            //             self.cam.change_dir(y_diff as f32 / 300.0, x_diff as f32 / 300.0);
            //             window.set_cursor_position(middle_x as i32, middle_y as i32);
            //         }
            //     }
            //     EventResponse::Continue
            // }

            _ => EventResponse::NotHandled,
        }
    }
}
<commit_msg>remove comment<commit_after>use super::camera::*;
use super::event_manager::*;
use glium::backend::glutin_backend::GlutinFacade;
use glium::glutin::{CursorState, ElementState, Event, MouseButton, VirtualKeyCode};

pub struct Ghost {
    cam: Camera,
    prev_mouse_pos: Option<(i32, i32)>,
    context: GlutinFacade,
}

impl Ghost {
    pub fn new(context: GlutinFacade) -> Self {
        Ghost {
            cam: Camera::default(),
            prev_mouse_pos: None,
            context: context,
        }
    }

    pub fn get_camera(&self) -> Camera {
        self.cam
    }
}

/// **Implements Controls**
/// *W => FORWARD
/// *A => LEFT
/// *S => BACKWARDS
/// *D => RIGHT
/// *'Space' => UP
/// *'LControl' => DOWN (only accepts one keystroke (cannot hold LControl to go
/// down))
/// *'C' => DOWN (as a replacement for 'LControl')

/// MouseMovement for changing the direction the camera looks
impl EventHandler for Ghost {
    fn handle_event(&mut self, e: &Event) -> EventResponse {
        match *e {
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::W)) => {
                self.cam.move_forward(1.0);
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::S)) => {
                self.cam.move_backward(1.0);
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::A)) => {
                self.cam.move_left(1.0);
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::D)) => {
                self.cam.move_right(1.0);
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::Space)) => {
                self.cam.move_up(1.0);
                EventResponse::Continue
            }
            // X only for the fact, that you cannot hold LControl to go down,
            // because holding the key only counts as one keystroke
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::C)) => {
                self.cam.move_down(1.0);
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::LControl)) => {
                self.cam.move_down(1.0);
                EventResponse::Continue
            }

            Event::MouseInput(ElementState::Pressed, MouseButton::Left) => {
                info!("clicked");
                if let Some(window) = self.context.get_window() {
                    let res = window.set_cursor_state(CursorState::Hide);
                    warn!("{:?}", res);
                } else {
                    warn!("Failed to obtain window from facade");
                }
                EventResponse::Continue
            }
            Event::MouseMoved(x, y) => {

                if let Some((prev_x, prev_y)) = self.prev_mouse_pos {
                    let x_diff = x - prev_x;
                    let y_diff = y - prev_y;
                    info!("x = {}, y = {}", x_diff, y_diff);
                    self.cam.change_dir(y_diff as f32 / 300.0, -x_diff as f32 / 300.0);
                }

                self.prev_mouse_pos = Some((x, y));

                EventResponse::Continue
            }
            _ => EventResponse::NotHandled,
        }
    }
}
<|endoftext|>


<commit_before>use super::camera::*;
use super::event_manager::*;
use glium::backend::glutin_backend::GlutinFacade;
use glium::glutin::{CursorState, ElementState, Event, MouseButton, VirtualKeyCode};

pub struct Ghost {
    cam: Camera,
    context: GlutinFacade,
    forward: bool,
    backward: bool,
    left: bool,
    right: bool,
    up: bool,
    down: bool,
    mouselock: bool,
}

impl Ghost {
    pub fn new(context: GlutinFacade) -> Self {
        Ghost {
            cam: Camera::default(),
            context: context,
            forward: false,
            backward: false,
            left: false,
            right: false,
            up: false,
            down: false,
            mouselock: false,
        }
    }
    pub fn update(&mut self) {
        if self.forward {
            self.cam.move_forward(1.0);
        }
        if self.backward {
            self.cam.move_backward(1.0);
        }
        if self.left {
            self.cam.move_left(1.0);
        }
        if self.right {
            self.cam.move_right(1.0);
        }
        if self.up {
            self.cam.move_up(1.0);
        }
        if self.down {
            self.cam.move_down(1.0);
        }
    }

    pub fn get_camera(&self) -> Camera {
        self.cam
    }
}

/// **Implements Controls**
/// *W => FORWARD
/// *A => LEFT
/// *S => BACKWARDS
/// *D => RIGHT
/// *'Space' => UP
/// *'LControl' => DOWN (only accepts one keystroke (cannot hold LControl to go
/// down))
/// *'C' => DOWN (as a replacement for 'LControl')

/// MouseMovement for changing the direction the camera looks
impl EventHandler for Ghost {
    fn handle_event(&mut self, e: &Event) -> EventResponse {
        match *e {
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::W)) => {
                self.forward = true;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Released, _, Some(VirtualKeyCode::W)) => {
                self.forward = false;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::S)) => {
                self.backward = true;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Released, _, Some(VirtualKeyCode::S)) => {
                self.backward = false;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::A)) => {
                self.left = true;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Released, _, Some(VirtualKeyCode::A)) => {
                self.left = false;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::D)) => {
                self.right = true;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Released, _, Some(VirtualKeyCode::D)) => {
                self.right = false;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::Space)) => {
                self.up = true;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Released, _, Some(VirtualKeyCode::Space)) => {
                self.up = false;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::LControl)) => {
                self.down = true;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Released, _, Some(VirtualKeyCode::LControl)) => {
                self.down = false;
                EventResponse::Continue
            }

            Event::MouseInput(ElementState::Pressed, MouseButton::Left) => {
                if !self.mouselock {
                    self.mouselock = true;
                    if let Some(window) = self.context.get_window() {
                        window.set_cursor_state(CursorState::Hide)
                            .expect("failed to set cursor state");
                    } else {
                        warn!("Failed to obtain window from facade");
                    }
                } else if self.mouselock {
                    self.mouselock = false;

                    if let Some(window) = self.context.get_window() {
                        window.set_cursor_state(CursorState::Normal)
                            .expect("failed to set cursor state");
                    } else {
                        warn!("Failed to obtain window from facade");
                    }
                }

                EventResponse::Continue
            }

            Event::MouseMoved(x, y) => {
                if self.mouselock {
                    if let Some(window) = self.context.get_window() {
                        // Possibility of mouse being outside of window without it resetting to the
                        // middle?
                        if let Some(middle) = window.get_inner_size_pixels() {
                            let middle_x = (middle.0 as i32) / 2;
                            let middle_y = (middle.1 as i32) / 2;
                            let x_diff = x - middle_x;
                            let y_diff = y - middle_y;
                            self.cam.change_dir(y_diff as f32 / 300.0, -x_diff as f32 / 300.0);
                            window.set_cursor_position(middle_x as i32, middle_y as i32)
                                .expect("setting cursor position failed");
                        }
                    }
                }
                EventResponse::Continue
            }
            _ => EventResponse::NotHandled,
        }
    }
}
<commit_msg>Add modification of speed with shift key<commit_after>use super::camera::*;
use super::event_manager::*;
use glium::backend::glutin_backend::GlutinFacade;
use glium::glutin::{CursorState, ElementState, Event, MouseButton, VirtualKeyCode};

pub struct Ghost {
    cam: Camera,
    context: GlutinFacade,
    speed: f32,
    forward: bool,
    backward: bool,
    left: bool,
    right: bool,
    up: bool,
    down: bool,
    mouselock: bool,
}

const DEFAULT_SPEED: f32 = 0.2;
const SHIFT_SPEED: f32 = 1.0;

impl Ghost {
    pub fn new(context: GlutinFacade) -> Self {
        Ghost {
            cam: Camera::default(),
            context: context,
            speed: DEFAULT_SPEED,
            forward: false,
            backward: false,
            left: false,
            right: false,
            up: false,
            down: false,
            mouselock: false,
        }
    }
    pub fn update(&mut self) {
        if self.forward {
            self.cam.move_forward(self.speed);
        }
        if self.backward {
            self.cam.move_backward(self.speed);
        }
        if self.left {
            self.cam.move_left(self.speed);
        }
        if self.right {
            self.cam.move_right(self.speed);
        }
        if self.up {
            self.cam.move_up(self.speed);
        }
        if self.down {
            self.cam.move_down(self.speed);
        }
    }

    pub fn get_camera(&self) -> Camera {
        self.cam
    }
}

/// **Implements Controls**
/// *W => FORWARD
/// *A => LEFT
/// *S => BACKWARDS
/// *D => RIGHT
/// *'Space' => UP
/// *'LControl' => DOWN (only accepts one keystroke (cannot hold LControl to go
/// down))
/// *'C' => DOWN (as a replacement for 'LControl')

/// MouseMovement for changing the direction the camera looks
impl EventHandler for Ghost {
    fn handle_event(&mut self, e: &Event) -> EventResponse {
        match *e {
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::W)) => {
                self.forward = true;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Released, _, Some(VirtualKeyCode::W)) => {
                self.forward = false;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::S)) => {
                self.backward = true;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Released, _, Some(VirtualKeyCode::S)) => {
                self.backward = false;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::A)) => {
                self.left = true;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Released, _, Some(VirtualKeyCode::A)) => {
                self.left = false;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::D)) => {
                self.right = true;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Released, _, Some(VirtualKeyCode::D)) => {
                self.right = false;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::Space)) => {
                self.up = true;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Released, _, Some(VirtualKeyCode::Space)) => {
                self.up = false;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::LControl)) => {
                self.down = true;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Released, _, Some(VirtualKeyCode::LControl)) => {
                self.down = false;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Pressed, _, Some(VirtualKeyCode::LShift)) => {
                self.speed = SHIFT_SPEED;
                EventResponse::Continue
            }
            Event::KeyboardInput(ElementState::Released, _, Some(VirtualKeyCode::LShift)) => {
                self.speed = DEFAULT_SPEED;
                EventResponse::Continue
            }

            Event::MouseInput(ElementState::Pressed, MouseButton::Left) => {
                if !self.mouselock {
                    self.mouselock = true;
                    if let Some(window) = self.context.get_window() {
                        window.set_cursor_state(CursorState::Hide)
                            .expect("failed to set cursor state");
                    } else {
                        warn!("Failed to obtain window from facade");
                    }
                } else if self.mouselock {
                    self.mouselock = false;

                    if let Some(window) = self.context.get_window() {
                        window.set_cursor_state(CursorState::Normal)
                            .expect("failed to set cursor state");
                    } else {
                        warn!("Failed to obtain window from facade");
                    }
                }

                EventResponse::Continue
            }

            Event::MouseMoved(x, y) => {
                if self.mouselock {
                    if let Some(window) = self.context.get_window() {
                        // Possibility of mouse being outside of window without it resetting to the
                        // middle?
                        if let Some(middle) = window.get_inner_size_pixels() {
                            let middle_x = (middle.0 as i32) / 2;
                            let middle_y = (middle.1 as i32) / 2;
                            let x_diff = x - middle_x;
                            let y_diff = y - middle_y;
                            self.cam.change_dir(y_diff as f32 / 300.0, -x_diff as f32 / 300.0);
                            window.set_cursor_position(middle_x as i32, middle_y as i32)
                                .expect("setting cursor position failed");
                        }
                    }
                }
                EventResponse::Continue
            }
            _ => EventResponse::NotHandled,
        }
    }
}
<|endoftext|>


<commit_before>extern crate pencil;

use pencil::Pencil;
use pencil::{Request, Params, PencilResult, PenValue};

fn user(_: Request, params: Params) -> PencilResult {
    PenValue(format!("user {}", params[0]))
}

fn main() {
    let mut app = Pencil::new("/web/example");
    app.route(r"/user/(\d+)", &["GET"], "user", user);
    app.run();
}
<commit_msg>Fixed hello example<commit_after>extern crate pencil;

use pencil::Pencil;
use pencil::{Request, Params, PencilResult, PenString};

fn user(_: Request, params: Params) -> PencilResult {
    Ok(PenString(format!("user {}", params[0])))
}

fn main() {
    let mut app = Pencil::new("/web/example");
    app.route(r"/user/(\d+)", &["GET"], "user", user);
    app.run();
}
<|endoftext|>


<commit_before>pub mod transforms;
pub mod datasets;<commit_msg>add newline to mod.rs<commit_after>pub mod transforms;
pub mod datasets;
<|endoftext|>


<commit_before>
<commit_msg>clock: Added template to lib.rs<commit_after>use std::{cmp, fmt};

pub struct Clock {
    hours: u8,
    minutes: u8,
}

impl Clock {
    pub fn new(hours: i32, minutes: i32) -> Self {
        unimplemented!(
            "Construct a new Clock from {} hours and {} minutes",
            hours,
            minutes
        );
    }

    pub fn add_minutes(self, minutes: i32) -> Self {
        unimplemented!("Add {} minutes to existing Clock time", minutes);
    }

    pub fn to_string(&self) -> String {
        unimplemented!("Return String representation of a Clock");
    }
}

impl fmt::Debug for Clock {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        unimplemented!("Return debug representation of a Clock");
    }
}

impl cmp::PartialEq for Clock {
    fn eq(&self, other: &Clock) -> bool {
        unimplemented!("Implement comparison between two Clocks");
    }
}
<|endoftext|>