<commit_before>//! This module provides a way to construct a `File`.
//! It is intended to be completely decoupled from the
//! parser, so as to allow to evolve the tree representation
//! and the parser algorithm independently.
//!
//! The `Sink` trait is the bridge between the parser and the
//! tree builder: the parser produces a stream of events like
//! `start node`, `finish node`, and `FileBuilder` converts
//! this stream to a real tree.
use crate::{
    lexer::Token,
    parser_impl::Sink,
    SmolStr,
    SyntaxKind::{self, *},
    TextRange, TextUnit,
    yellow::syntax_error::{
        ParseError,
        SyntaxError,
        SyntaxErrorKind,
    },
};
use std::mem;

/// `Parser` produces a flat list of `Event`s.
/// They are converted to a tree-structure in
/// a separate pass, via `TreeBuilder`.
#[derive(Debug)]
pub(crate) enum Event {
    /// This event signifies the start of the node.
    /// It should be either abandoned (in which case the
    /// `kind` is `TOMBSTONE`, and the event is ignored),
    /// or completed via a `Finish` event.
    ///
    /// All tokens between a `Start` and a `Finish` would
    /// become the children of the respective node.
    ///
    /// For left-recursive syntactic constructs, the parser produces
    /// a child node before it sees a parent. `forward_parent`
    /// saves the position of current event's parent.
    ///
    /// Consider this path
    ///
    /// foo::bar
    ///
    /// The events for it would look like this:
    ///
    ///
    /// START(PATH) IDENT('foo') FINISH START(PATH) COLONCOLON IDENT('bar') FINISH
    ///       |                          /\
    ///       |                          |
    ///       +------forward-parent------+
    ///
    /// And the tree would look like this
    ///
    ///    +--PATH---------+
    ///    |   |           |
    ///    |   |           |
    ///    |  '::'       'bar'
    ///    |
    ///   PATH
    ///    |
    ///   'foo'
    ///
    /// See also `CompletedMarker::precede`.
    Start {
        kind: SyntaxKind,
        forward_parent: Option<u32>,
    },

    /// Complete the previous `Start` event
    Finish,

    /// Produce a single leaf-element.
    /// `n_raw_tokens` is used to glue complex contextual tokens.
    /// For example, lexer tokenizes `>>` as `>`, `>`, and
    /// `n_raw_tokens = 2` is used to produced a single `>>`.
    Token {
        kind: SyntaxKind,
        n_raw_tokens: u8,
    },

    Error {
        msg: ParseError,
    },
}

impl Event {
    pub(crate) fn tombstone() -> Self {
        Event::Start {
            kind: TOMBSTONE,
            forward_parent: None,
        }
    }
}

pub(super) struct EventProcessor<'a, S: Sink> {
    sink: S,
    text_pos: TextUnit,
    text: &'a str,
    token_pos: usize,
    tokens: &'a [Token],
    events: &'a mut [Event],
}

impl<'a, S: Sink> EventProcessor<'a, S> {
    pub(super) fn new(
        sink: S,
        text: &'a str,
        tokens: &'a [Token],
        events: &'a mut [Event],
    ) -> EventProcessor<'a, S> {
        EventProcessor {
            sink,
            text_pos: 0.into(),
            text,
            token_pos: 0,
            tokens,
            events,
        }
    }

    /// Generate the syntax tree with the control of events.
    pub(super) fn process(mut self) -> S {
        let mut forward_parents = Vec::new();

        for i in 0..self.events.len() {
            match mem::replace(&mut self.events[i], Event::tombstone()) {
                Event::Start {
                    kind: TOMBSTONE, ..
                } => (),

                Event::Start {
                    kind,
                    forward_parent,
                } => {
                    // For events[A, B, C], B is A's forward_parent, C is B's forward_parent,
                    // in the normal control flow, the parent-child relation: `A -> B -> C`,
                    // while with the magic forward_parent, it writes: `C <- B <- A`.

                    // append `A` into parents.
                    forward_parents.push(kind);
                    let mut idx = i;
                    let mut fp = forward_parent;
                    while let Some(fwd) = fp {
                        idx += fwd as usize;
                        // append `A`'s forward_parent `B`
                        fp = match mem::replace(&mut self.events[idx], Event::tombstone()) {
                            Event::Start {
                                kind,
                                forward_parent,
                            } => {
                                forward_parents.push(kind);
                                forward_parent
                            }
                            _ => unreachable!(),
                        };
                        // append `B`'s forward_parent `C` in the next stage.
                    }

                    for kind in forward_parents.drain(..).rev() {
                        self.start(kind);
                    }
                }
                Event::Finish => {
                    let is_last = i == self.events.len() - 1;
                    self.finish(is_last);
                }
                Event::Token { kind, n_raw_tokens } => {
                    self.eat_trivias();
                    let n_raw_tokens = n_raw_tokens as usize;
                    let len = self.tokens[self.token_pos..self.token_pos + n_raw_tokens]
                        .iter()
                        .map(|it| it.len)
                        .sum::<TextUnit>();
                    self.leaf(kind, len, n_raw_tokens);
                }
                Event::Error { msg } => self.sink.error(SyntaxError::new(
                    SyntaxErrorKind::ParseError(msg),
                    self.text_pos,
                )),
            }
        }
        self.sink
    }

    /// Add the node into syntax tree but discard the comments/whitespaces.
    fn start(&mut self, kind: SyntaxKind) {
        if kind == SOURCE_FILE {
            self.sink.start_branch(kind);
            return;
        }
        let n_trivias = self.tokens[self.token_pos..]
            .iter()
            .take_while(|it| it.kind.is_trivia())
            .count();
        let leading_trivias = &self.tokens[self.token_pos..self.token_pos + n_trivias];
        let mut trivia_end =
            self.text_pos + leading_trivias.iter().map(|it| it.len).sum::<TextUnit>();

        let n_attached_trivias = {
            let leading_trivias = leading_trivias.iter().rev().map(|it| {
                let next_end = trivia_end - it.len;
                let range = TextRange::from_to(next_end, trivia_end);
                trivia_end = next_end;
                (it.kind, &self.text[range])
            });
            n_attached_trivias(kind, leading_trivias)
        };
        self.eat_n_trivias(n_trivias - n_attached_trivias);
        self.sink.start_branch(kind);
        self.eat_n_trivias(n_attached_trivias);
    }

    fn finish(&mut self, is_last: bool) {
        if is_last {
            self.eat_trivias()
        }
        self.sink.finish_branch();
    }

    fn eat_trivias(&mut self) {
        while let Some(&token) = self.tokens.get(self.token_pos) {
            if !token.kind.is_trivia() {
                break;
            }
            self.leaf(token.kind, token.len, 1);
        }
    }

    fn eat_n_trivias(&mut self, n: usize) {
        for _ in 0..n {
            let token = self.tokens[self.token_pos];
            assert!(token.kind.is_trivia());
            self.leaf(token.kind, token.len, 1);
        }
    }

    fn leaf(&mut self, kind: SyntaxKind, len: TextUnit, n_tokens: usize) {
        let range = TextRange::offset_len(self.text_pos, len);
        let text: SmolStr = self.text[range].into();
        self.text_pos += len;
        self.token_pos += n_tokens;
        self.sink.leaf(kind, text);
    }
}

fn n_attached_trivias<'a>(
    kind: SyntaxKind,
    trivias: impl Iterator<Item = (SyntaxKind, &'a str)>,
) -> usize {
    // FIXME: parse attached trivias of CONST_DEF/TYPE_DEF
    match kind {
        STRUCT_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | MODULE => {
            let mut res = 0;
            for (i, (kind, text)) in trivias.enumerate() {
                match kind {
                    WHITESPACE => {
                        if text.contains("\n\n") {
                            break;
                        }
                    }
                    COMMENT => {
                        res = i + 1;
                    }
                    _ => (),
                }
            }
            res
        }
        _ => 0,
    }
}
<commit_msg>consume trivias for type/const def<commit_after>//! This module provides a way to construct a `File`.
//! It is intended to be completely decoupled from the
//! parser, so as to allow to evolve the tree representation
//! and the parser algorithm independently.
//!
//! The `Sink` trait is the bridge between the parser and the
//! tree builder: the parser produces a stream of events like
//! `start node`, `finish node`, and `FileBuilder` converts
//! this stream to a real tree.
use crate::{
    lexer::Token,
    parser_impl::Sink,
    SmolStr,
    SyntaxKind::{self, *},
    TextRange, TextUnit,
    yellow::syntax_error::{
        ParseError,
        SyntaxError,
        SyntaxErrorKind,
    },
};
use std::mem;

/// `Parser` produces a flat list of `Event`s.
/// They are converted to a tree-structure in
/// a separate pass, via `TreeBuilder`.
#[derive(Debug)]
pub(crate) enum Event {
    /// This event signifies the start of the node.
    /// It should be either abandoned (in which case the
    /// `kind` is `TOMBSTONE`, and the event is ignored),
    /// or completed via a `Finish` event.
    ///
    /// All tokens between a `Start` and a `Finish` would
    /// become the children of the respective node.
    ///
    /// For left-recursive syntactic constructs, the parser produces
    /// a child node before it sees a parent. `forward_parent`
    /// saves the position of current event's parent.
    ///
    /// Consider this path
    ///
    /// foo::bar
    ///
    /// The events for it would look like this:
    ///
    ///
    /// START(PATH) IDENT('foo') FINISH START(PATH) COLONCOLON IDENT('bar') FINISH
    ///       |                          /\
    ///       |                          |
    ///       +------forward-parent------+
    ///
    /// And the tree would look like this
    ///
    ///    +--PATH---------+
    ///    |   |           |
    ///    |   |           |
    ///    |  '::'       'bar'
    ///    |
    ///   PATH
    ///    |
    ///   'foo'
    ///
    /// See also `CompletedMarker::precede`.
    Start {
        kind: SyntaxKind,
        forward_parent: Option<u32>,
    },

    /// Complete the previous `Start` event
    Finish,

    /// Produce a single leaf-element.
    /// `n_raw_tokens` is used to glue complex contextual tokens.
    /// For example, lexer tokenizes `>>` as `>`, `>`, and
    /// `n_raw_tokens = 2` is used to produced a single `>>`.
    Token {
        kind: SyntaxKind,
        n_raw_tokens: u8,
    },

    Error {
        msg: ParseError,
    },
}

impl Event {
    pub(crate) fn tombstone() -> Self {
        Event::Start {
            kind: TOMBSTONE,
            forward_parent: None,
        }
    }
}

pub(super) struct EventProcessor<'a, S: Sink> {
    sink: S,
    text_pos: TextUnit,
    text: &'a str,
    token_pos: usize,
    tokens: &'a [Token],
    events: &'a mut [Event],
}

impl<'a, S: Sink> EventProcessor<'a, S> {
    pub(super) fn new(
        sink: S,
        text: &'a str,
        tokens: &'a [Token],
        events: &'a mut [Event],
    ) -> EventProcessor<'a, S> {
        EventProcessor {
            sink,
            text_pos: 0.into(),
            text,
            token_pos: 0,
            tokens,
            events,
        }
    }

    /// Generate the syntax tree with the control of events.
    pub(super) fn process(mut self) -> S {
        let mut forward_parents = Vec::new();

        for i in 0..self.events.len() {
            match mem::replace(&mut self.events[i], Event::tombstone()) {
                Event::Start {
                    kind: TOMBSTONE, ..
                } => (),

                Event::Start {
                    kind,
                    forward_parent,
                } => {
                    // For events[A, B, C], B is A's forward_parent, C is B's forward_parent,
                    // in the normal control flow, the parent-child relation: `A -> B -> C`,
                    // while with the magic forward_parent, it writes: `C <- B <- A`.

                    // append `A` into parents.
                    forward_parents.push(kind);
                    let mut idx = i;
                    let mut fp = forward_parent;
                    while let Some(fwd) = fp {
                        idx += fwd as usize;
                        // append `A`'s forward_parent `B`
                        fp = match mem::replace(&mut self.events[idx], Event::tombstone()) {
                            Event::Start {
                                kind,
                                forward_parent,
                            } => {
                                forward_parents.push(kind);
                                forward_parent
                            }
                            _ => unreachable!(),
                        };
                        // append `B`'s forward_parent `C` in the next stage.
                    }

                    for kind in forward_parents.drain(..).rev() {
                        self.start(kind);
                    }
                }
                Event::Finish => {
                    let is_last = i == self.events.len() - 1;
                    self.finish(is_last);
                }
                Event::Token { kind, n_raw_tokens } => {
                    self.eat_trivias();
                    let n_raw_tokens = n_raw_tokens as usize;
                    let len = self.tokens[self.token_pos..self.token_pos + n_raw_tokens]
                        .iter()
                        .map(|it| it.len)
                        .sum::<TextUnit>();
                    self.leaf(kind, len, n_raw_tokens);
                }
                Event::Error { msg } => self.sink.error(SyntaxError::new(
                    SyntaxErrorKind::ParseError(msg),
                    self.text_pos,
                )),
            }
        }
        self.sink
    }

    /// Add the node into syntax tree but discard the comments/whitespaces.
    fn start(&mut self, kind: SyntaxKind) {
        if kind == SOURCE_FILE {
            self.sink.start_branch(kind);
            return;
        }
        let n_trivias = self.tokens[self.token_pos..]
            .iter()
            .take_while(|it| it.kind.is_trivia())
            .count();
        let leading_trivias = &self.tokens[self.token_pos..self.token_pos + n_trivias];
        let mut trivia_end =
            self.text_pos + leading_trivias.iter().map(|it| it.len).sum::<TextUnit>();

        let n_attached_trivias = {
            let leading_trivias = leading_trivias.iter().rev().map(|it| {
                let next_end = trivia_end - it.len;
                let range = TextRange::from_to(next_end, trivia_end);
                trivia_end = next_end;
                (it.kind, &self.text[range])
            });
            n_attached_trivias(kind, leading_trivias)
        };
        self.eat_n_trivias(n_trivias - n_attached_trivias);
        self.sink.start_branch(kind);
        self.eat_n_trivias(n_attached_trivias);
    }

    fn finish(&mut self, is_last: bool) {
        if is_last {
            self.eat_trivias()
        }
        self.sink.finish_branch();
    }

    fn eat_trivias(&mut self) {
        while let Some(&token) = self.tokens.get(self.token_pos) {
            if !token.kind.is_trivia() {
                break;
            }
            self.leaf(token.kind, token.len, 1);
        }
    }

    fn eat_n_trivias(&mut self, n: usize) {
        for _ in 0..n {
            let token = self.tokens[self.token_pos];
            assert!(token.kind.is_trivia());
            self.leaf(token.kind, token.len, 1);
        }
    }

    fn leaf(&mut self, kind: SyntaxKind, len: TextUnit, n_tokens: usize) {
        let range = TextRange::offset_len(self.text_pos, len);
        let text: SmolStr = self.text[range].into();
        self.text_pos += len;
        self.token_pos += n_tokens;
        self.sink.leaf(kind, text);
    }
}

fn n_attached_trivias<'a>(
    kind: SyntaxKind,
    trivias: impl Iterator<Item = (SyntaxKind, &'a str)>,
) -> usize {
    match kind {
        CONST_DEF | TYPE_DEF | STRUCT_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | MODULE => {
            let mut res = 0;
            for (i, (kind, text)) in trivias.enumerate() {
                match kind {
                    WHITESPACE => {
                        if text.contains("\n\n") {
                            break;
                        }
                    }
                    COMMENT => {
                        res = i + 1;
                    }
                    _ => (),
                }
            }
            res
        }
        _ => 0,
    }
}
<|endoftext|>


<commit_before>use crate::error::{Error,
                   Result};
use blake2b_simd::{Params,
                   State};
use hex::FromHex;
use serde::Serialize;
use std::{convert::TryInto,
          fmt,
          fs::File,
          io::{BufReader,
               Read},
          path::Path,
          str::FromStr};

/// When hashing byte streams, we'll read 1KB at a time, adding this to the
/// internal hashing state as we compute the final digest.
const BUF_SIZE: usize = 1024;

/// The size of our Blake2b hash digests (32 bytes)
const HASH_DIGEST_SIZE: usize = 32;

/// Convenience wrapper type for a 32-byte Blake2b hash digest.
///
/// Implements secure equality comparison, as well as hex-encoding via
/// `std::fmt::Display`.
///
/// There are intentionally no explicit constructors; to get a
/// instance, you'll need to either convert it directly from a `&[u8]`
/// or parse it from a hex string.
#[derive(Clone, Debug)]
pub struct Blake2bHash {
    digest:     [u8; HASH_DIGEST_SIZE],
    /// Temporary field to support Deref<str> for backwards
    /// compatibility with Builder until it can use the new types.
    hex_string: String,
}

impl Blake2bHash {
    /// Temporary constructor while we store the hex encoding in the
    /// type directly.
    fn new(digest: [u8; HASH_DIGEST_SIZE]) -> Self {
        let hex_string = hex::encode(&digest).to_lowercase();
        Blake2bHash { digest, hex_string }
    }
}

impl From<blake2b_simd::Hash> for Blake2bHash {
    fn from(src: blake2b_simd::Hash) -> Self {
        let digest = src.as_bytes()
                        .try_into()
                        .expect("We know we can safely convert to a byte array");
        Blake2bHash::new(digest)
    }
}

impl AsRef<[u8]> for Blake2bHash {
    fn as_ref(&self) -> &[u8] { &self.digest }
}

impl PartialEq for Blake2bHash {
    /// Implement secure equality comparison for our hashes here so we
    /// don't have to think about it elsewhere.
    // Strictly speaking, secure equality comparison shouldn't be
    // necessary; however, having a type encapsulate this gives us a
    // convenient way to modify this in the future.
    fn eq(&self, other: &Blake2bHash) -> bool { crate::crypto::secure_eq(self, other) }
}

impl Eq for Blake2bHash {}

impl fmt::Display for Blake2bHash {
    /// Displays a Blake2bHash as a lowercase hex-encoded string.
    ///
    /// Due to historical precedent, the lowercasing *is* significant,
    /// as we sign the lowercase hex-encoded version of a Blake2b
    /// hash, and not simply the Blake2b hash itself, when we sign a
    /// HART file.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // hex::encode currently outputs lowercase strings, but we
        // want to strictly enforce this and guard against any future
        // changes to that crate.
        hex::encode(self).to_lowercase().fmt(f)
    }
}

impl FromStr for Blake2bHash {
    type Err = Error;

    /// Convert a hex-encoded byte string into a Blake2bHash. Ensures
    /// the string represents a byte array of proper length.
    ///
    /// Case of the incoming string is not significant (e.g.,
    /// "DEADBEEF" and "deadbeef" are equivalent).
    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
        // FromHex has an implementation for [u8; 32], so this ensures
        // the proper length of bytes... well, that and the compiler,
        // of course :)
        FromHex::from_hex(s).map(Self::new).map_err(|e| {
                                               Error::CryptoError(format!("Could not parse \
                                                                           Blake2bHash from \
                                                                           string: {}",
                                                                          e))
                                           })
    }
}

impl Serialize for Blake2bHash {
    /// Serializes a `Blake2bHash` according to its `Display`
    /// implementation (i.e., a lowercase hex-encoded string).
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
        where S: serde::Serializer
    {
        serializer.serialize_str(&self.to_string())
    }
}

////////////////////////////////////////////////////////////////////////

/// Initialize the hasher state. In particular, set the digest length
/// to 32 bytes. All hashing functions must use this to ensure
/// consistency!
fn hash_state() -> State {
    let mut params = Params::new();
    params.hash_length(HASH_DIGEST_SIZE);
    params.to_state()
}

/// Calculate the BLAKE2b hash of a file.
/// NOTE: the hashing is keyless
pub fn hash_file<P>(filename: P) -> Result<Blake2bHash>
    where P: AsRef<Path>
{
    let file = File::open(filename.as_ref())?;
    let mut reader = BufReader::new(file);
    hash_reader(&mut reader)
}

pub fn hash_bytes<B>(data: B) -> Blake2bHash
    where B: AsRef<[u8]>
{
    let mut state = hash_state();
    state.update(data.as_ref());
    state.finalize().into()
}

pub fn hash_reader(reader: &mut dyn Read) -> Result<Blake2bHash> {
    let mut state = hash_state();

    let mut buf = [0u8; BUF_SIZE];
    loop {
        let bytes_read = reader.read(&mut buf)?;
        if bytes_read == 0 {
            break;
        }
        let chunk = &buf[0..bytes_read];
        state.update(chunk);
    }

    Ok(state.finalize().into())
}

#[cfg(test)]
mod test {
    #[allow(unused_imports)]
    use std::fs::{self,
                  File};
    #[allow(unused_imports)]
    use std::io;

    use super::{super::test_support::*,
                *};

    /// Helper function to create a Blake2bHash directly from a
    /// hex-encoded string.
    fn hash_from_hex(hex: &str) -> Blake2bHash { hex.parse().unwrap() }

    #[test]
    fn hash_file_working() {
        // The expected values were computed using the `b2sum` program from
        // https://github.com/dchest/b2sum using the the `-s=32` option. For example:
        //      b2sum -s=32 signme.dat

        let computed = hash_file(&fixture("signme.dat")).unwrap();
        let expected =
            hash_from_hex("20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233");
        assert_eq!(computed, expected);

        let computed = hash_file(&fixture("happyhumans-20160424223347.sig.key")).unwrap();
        let expected =
            hash_from_hex("e966844bbc50b7a3a6d81e94dd38e27b92814b944095a8e55f1780921bfcfbe1");
        assert_eq!(computed, expected);

        let computed = hash_file(&fixture("happyhumans-20160424223347.pub")).unwrap();
        let expected =
            hash_from_hex("b80c4f412f9a0a7727b6e6f115e1b5fa3bae79ad2fcf47f769ed4e42cfb12265");
        assert_eq!(computed, expected);
    }

    #[test]
    fn strings_can_be_hashed() {
        let message = "supercalifragilisticexpialadocious";
        let expected =
            hash_from_hex("2ca8ebafca7e189de2a36125b92a1db20f393d1e2708f5daa55e51cf05114437");
        let actual = hash_bytes(message);

        assert_eq!(expected, actual);
    }

    #[test]
    fn bytes_can_be_hashed() {
        let message = [0u8, 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8];
        let expected =
            hash_from_hex("8b57a796a5d07cb04cc1614dfc2acb3f73edc712d7f433619ca3bbe66bb15f49");
        let actual = hash_bytes(&message);

        assert_eq!(expected, actual);
    }

    #[test]
    #[cfg(feature = "functional")]
    fn hash_file_large_binary() {
        let dir = tempfile::Builder::new().prefix("large_file")
                                          .tempdir()
                                          .unwrap();

        let url = "http://www.kernel.org/pub/linux/kernel/v4.x/linux-4.3.tar.gz";
        let file = dir.path().join(url.rsplit('/').next().unwrap());

        // Download the doc to the temp directory
        let mut f = File::create(&file).unwrap();
        let mut res = reqwest::blocking::get(url).unwrap();
        res.copy_to(&mut f).unwrap();

        let computed = Blake2bHash::from_file(&file).unwrap();
        let expected =
            hash_from_hex("ba640dc063f0ed27e60b38dbb7cf19778cf7805d9fc91eb129fb68b409d46414");
        assert_eq!(computed, expected);
    }

    mod blake2bhash {
        use super::*;

        #[test]
        fn eq() {
            let zeroes = Blake2bHash::new([0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
                                           0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
                                           0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8]);

            let ones = Blake2bHash::new([1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                         1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                         1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8]);

            assert_ne!(zeroes, ones);
            assert_eq!(zeroes, zeroes);
            assert_eq!(ones, ones);
        }

        #[test]
        fn display() {
            let ones = Blake2bHash::new([1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                         1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                         1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8]);
            assert_eq!(ones.to_string(),
                       "0101010101010101010101010101010101010101010101010101010101010101");
        }

        #[test]
        fn from_str_good() {
            // Exactly 32 bytes long
            let h = "0101010101010101010101010101010101010101010101010101010101010101".parse::<Blake2bHash>();
            assert!(h.is_ok());
        }

        #[test]
        fn from_str_short() {
            // This is one byte too short
            let h = "01010101010101010101010101010101010101010101010101010101010101".parse::<Blake2bHash>();
            assert!(h.is_err());
        }
        #[test]
        fn from_str_long() {
            // This is one byte too long
            let h = "010101010101010101010101010101010101010101010101010101010101010101".parse::<Blake2bHash>();
            assert!(h.is_err());
        }

        #[test]
        fn from_str_case_is_insignificant() {
            let lower_case = "20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233";
            let upper_case = "20590A52C4F00588C500328B16D466C982A26FABAA5FA4DCC83052DD0A84F233";

            let l = lower_case.parse::<Blake2bHash>().unwrap();
            let u = upper_case.parse::<Blake2bHash>().unwrap();

            assert_eq!(l, u);
        }

        #[test]
        fn from_str_display_round_trip() {
            let input = "20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233";
            let output = input.parse::<Blake2bHash>().unwrap().to_string();
            assert_eq!(output, input);
        }

        #[test]
        fn serialize_as_hex_encoding() {
            let input = "20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233";
            let hash: Blake2bHash = input.parse().unwrap();
            serde_test::assert_ser_tokens(&hash, &[serde_test::Token::Str(input)]);
        }
    }
}
<commit_msg>[REFACTOR] Delete inner hex_string field from Blake2bHash<commit_after>use crate::error::{Error,
                   Result};
use blake2b_simd::{Params,
                   State};
use hex::FromHex;
use serde::Serialize;
use std::{convert::TryInto,
          fmt,
          fs::File,
          io::{BufReader,
               Read},
          path::Path,
          str::FromStr};

/// When hashing byte streams, we'll read 1KB at a time, adding this to the
/// internal hashing state as we compute the final digest.
const BUF_SIZE: usize = 1024;

/// The size of our Blake2b hash digests (32 bytes)
const HASH_DIGEST_SIZE: usize = 32;

/// Convenience wrapper type for a 32-byte Blake2b hash digest.
///
/// Implements secure equality comparison, as well as hex-encoding via
/// `std::fmt::Display`.
///
/// There are intentionally no explicit constructors; to get a
/// instance, you'll need to either convert it directly from a `&[u8]`
/// or parse it from a hex string.
#[derive(Clone, Debug)]
pub struct Blake2bHash {
    digest:     [u8; HASH_DIGEST_SIZE]
}

impl Blake2bHash {
    /// Temporary constructor while we store the hex encoding in the
    /// type directly.
    fn new(digest: [u8; HASH_DIGEST_SIZE]) -> Self {
        Blake2bHash { digest }
    }
}

impl From<blake2b_simd::Hash> for Blake2bHash {
    fn from(src: blake2b_simd::Hash) -> Self {
        let digest = src.as_bytes()
                        .try_into()
                        .expect("We know we can safely convert to a byte array");
        Blake2bHash::new(digest)
    }
}

impl AsRef<[u8]> for Blake2bHash {
    fn as_ref(&self) -> &[u8] { &self.digest }
}

impl PartialEq for Blake2bHash {
    /// Implement secure equality comparison for our hashes here so we
    /// don't have to think about it elsewhere.
    // Strictly speaking, secure equality comparison shouldn't be
    // necessary; however, having a type encapsulate this gives us a
    // convenient way to modify this in the future.
    fn eq(&self, other: &Blake2bHash) -> bool { crate::crypto::secure_eq(self, other) }
}

impl Eq for Blake2bHash {}

impl fmt::Display for Blake2bHash {
    /// Displays a Blake2bHash as a lowercase hex-encoded string.
    ///
    /// Due to historical precedent, the lowercasing *is* significant,
    /// as we sign the lowercase hex-encoded version of a Blake2b
    /// hash, and not simply the Blake2b hash itself, when we sign a
    /// HART file.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // hex::encode currently outputs lowercase strings, but we
        // want to strictly enforce this and guard against any future
        // changes to that crate.
        hex::encode(self).to_lowercase().fmt(f)
    }
}

impl FromStr for Blake2bHash {
    type Err = Error;

    /// Convert a hex-encoded byte string into a Blake2bHash. Ensures
    /// the string represents a byte array of proper length.
    ///
    /// Case of the incoming string is not significant (e.g.,
    /// "DEADBEEF" and "deadbeef" are equivalent).
    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
        // FromHex has an implementation for [u8; 32], so this ensures
        // the proper length of bytes... well, that and the compiler,
        // of course :)
        FromHex::from_hex(s).map(Self::new).map_err(|e| {
                                               Error::CryptoError(format!("Could not parse \
                                                                           Blake2bHash from \
                                                                           string: {}",
                                                                          e))
                                           })
    }
}

impl Serialize for Blake2bHash {
    /// Serializes a `Blake2bHash` according to its `Display`
    /// implementation (i.e., a lowercase hex-encoded string).
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
        where S: serde::Serializer
    {
        serializer.serialize_str(&self.to_string())
    }
}

////////////////////////////////////////////////////////////////////////

/// Initialize the hasher state. In particular, set the digest length
/// to 32 bytes. All hashing functions must use this to ensure
/// consistency!
fn hash_state() -> State {
    let mut params = Params::new();
    params.hash_length(HASH_DIGEST_SIZE);
    params.to_state()
}

/// Calculate the BLAKE2b hash of a file.
/// NOTE: the hashing is keyless
pub fn hash_file<P>(filename: P) -> Result<Blake2bHash>
    where P: AsRef<Path>
{
    let file = File::open(filename.as_ref())?;
    let mut reader = BufReader::new(file);
    hash_reader(&mut reader)
}

pub fn hash_bytes<B>(data: B) -> Blake2bHash
    where B: AsRef<[u8]>
{
    let mut state = hash_state();
    state.update(data.as_ref());
    state.finalize().into()
}

pub fn hash_reader(reader: &mut dyn Read) -> Result<Blake2bHash> {
    let mut state = hash_state();

    let mut buf = [0u8; BUF_SIZE];
    loop {
        let bytes_read = reader.read(&mut buf)?;
        if bytes_read == 0 {
            break;
        }
        let chunk = &buf[0..bytes_read];
        state.update(chunk);
    }

    Ok(state.finalize().into())
}

#[cfg(test)]
mod test {
    #[allow(unused_imports)]
    use std::fs::{self,
                  File};
    #[allow(unused_imports)]
    use std::io;

    use super::{super::test_support::*,
                *};

    /// Helper function to create a Blake2bHash directly from a
    /// hex-encoded string.
    fn hash_from_hex(hex: &str) -> Blake2bHash { hex.parse().unwrap() }

    #[test]
    fn hash_file_working() {
        // The expected values were computed using the `b2sum` program from
        // https://github.com/dchest/b2sum using the the `-s=32` option. For example:
        //      b2sum -s=32 signme.dat

        let computed = hash_file(&fixture("signme.dat")).unwrap();
        let expected =
            hash_from_hex("20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233");
        assert_eq!(computed, expected);

        let computed = hash_file(&fixture("happyhumans-20160424223347.sig.key")).unwrap();
        let expected =
            hash_from_hex("e966844bbc50b7a3a6d81e94dd38e27b92814b944095a8e55f1780921bfcfbe1");
        assert_eq!(computed, expected);

        let computed = hash_file(&fixture("happyhumans-20160424223347.pub")).unwrap();
        let expected =
            hash_from_hex("b80c4f412f9a0a7727b6e6f115e1b5fa3bae79ad2fcf47f769ed4e42cfb12265");
        assert_eq!(computed, expected);
    }

    #[test]
    fn strings_can_be_hashed() {
        let message = "supercalifragilisticexpialadocious";
        let expected =
            hash_from_hex("2ca8ebafca7e189de2a36125b92a1db20f393d1e2708f5daa55e51cf05114437");
        let actual = hash_bytes(message);

        assert_eq!(expected, actual);
    }

    #[test]
    fn bytes_can_be_hashed() {
        let message = [0u8, 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8];
        let expected =
            hash_from_hex("8b57a796a5d07cb04cc1614dfc2acb3f73edc712d7f433619ca3bbe66bb15f49");
        let actual = hash_bytes(&message);

        assert_eq!(expected, actual);
    }

    #[test]
    #[cfg(feature = "functional")]
    fn hash_file_large_binary() {
        let dir = tempfile::Builder::new().prefix("large_file")
                                          .tempdir()
                                          .unwrap();

        let url = "http://www.kernel.org/pub/linux/kernel/v4.x/linux-4.3.tar.gz";
        let file = dir.path().join(url.rsplit('/').next().unwrap());

        // Download the doc to the temp directory
        let mut f = File::create(&file).unwrap();
        let mut res = reqwest::blocking::get(url).unwrap();
        res.copy_to(&mut f).unwrap();

        let computed = Blake2bHash::from_file(&file).unwrap();
        let expected =
            hash_from_hex("ba640dc063f0ed27e60b38dbb7cf19778cf7805d9fc91eb129fb68b409d46414");
        assert_eq!(computed, expected);
    }

    mod blake2bhash {
        use super::*;

        #[test]
        fn eq() {
            let zeroes = Blake2bHash::new([0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
                                           0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
                                           0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8]);

            let ones = Blake2bHash::new([1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                         1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                         1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8]);

            assert_ne!(zeroes, ones);
            assert_eq!(zeroes, zeroes);
            assert_eq!(ones, ones);
        }

        #[test]
        fn display() {
            let ones = Blake2bHash::new([1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                         1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8,
                                         1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8, 1u8]);
            assert_eq!(ones.to_string(),
                       "0101010101010101010101010101010101010101010101010101010101010101");
        }

        #[test]
        fn from_str_good() {
            // Exactly 32 bytes long
            let h = "0101010101010101010101010101010101010101010101010101010101010101".parse::<Blake2bHash>();
            assert!(h.is_ok());
        }

        #[test]
        fn from_str_short() {
            // This is one byte too short
            let h = "01010101010101010101010101010101010101010101010101010101010101".parse::<Blake2bHash>();
            assert!(h.is_err());
        }
        #[test]
        fn from_str_long() {
            // This is one byte too long
            let h = "010101010101010101010101010101010101010101010101010101010101010101".parse::<Blake2bHash>();
            assert!(h.is_err());
        }

        #[test]
        fn from_str_case_is_insignificant() {
            let lower_case = "20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233";
            let upper_case = "20590A52C4F00588C500328B16D466C982A26FABAA5FA4DCC83052DD0A84F233";

            let l = lower_case.parse::<Blake2bHash>().unwrap();
            let u = upper_case.parse::<Blake2bHash>().unwrap();

            assert_eq!(l, u);
        }

        #[test]
        fn from_str_display_round_trip() {
            let input = "20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233";
            let output = input.parse::<Blake2bHash>().unwrap().to_string();
            assert_eq!(output, input);
        }

        #[test]
        fn serialize_as_hex_encoding() {
            let input = "20590a52c4f00588c500328b16d466c982a26fabaa5fa4dcc83052dd0a84f233";
            let hash: Blake2bHash = input.parse().unwrap();
            serde_test::assert_ser_tokens(&hash, &[serde_test::Token::Str(input)]);
        }
    }
}
<|endoftext|>


<commit_before>//! Common PPU rendering code (used by sprite and BG rendering)
//!
//! # Terminology
//!
//! * **Tile**/**Character**: A tile consists of 8x8 or 16x16 pixels worth of color indices and is
//!   what makes up both sprites and backgrounds. Sprites are always made up of 8x8 tiles, while
//!   backgrounds can use 16x16 pixel tiles by setting the appropriate bit in `BGMODE ($2105)`.
//! * **Background**: A background is a big, connected layer of tiles that can (only) be moved as a
//!   unit. Depending on the background mode, between 1 and 4 BG layers can be used, each with
//!   between 4 and 256 colors.
//! * **Sprite**: A sprite is an independently movable object up to 64x64 pixels in size. Sprites
//!   always use 8x8 tiles and 16 colors, while each sprite can use a different palette. Sprites can
//!   not be rotated (rotating objects in games are either prerendered or make use of BG mode 7,
//!   which allows full matrix transformations on the layer).
//! * **Name table**/**Character table**/**Character map**: These tables store tile data: Maps of
//!   color indices to use for the tile's pixels. Sprites and all background modes except mode 7
//!   store the color indices in "bitplanes", which makes their decoding tricky: A bitplane stores 1
//!   bit for every pixel of the tile. Two bitplanes are interleaved: Bitplane 0 is stored in the
//!   low byte, while bitplane 1 is stored in the high byte.
//! * **Tile map**: Backgrounds consist of 1, 2 or 4 tile maps, each storing data for 32x32 tiles.
//!   For each tile on the background, the tile map stores the tile's priority and H/V flip bits,
//!   the palette, and the tile number. If 16x16 tiles are enabled, each entry in the tile map
//!   stores data for a 16x16 tile consisting of 4 8x8 tiles: `TILE`, `TILE+1`, `TILE+16` and
//!   `TILE+17`, where `TILE` is the stored tile number.

use super::{Ppu, Rgb};

/// An enum of all layers a pixel can come from
enum Layer {
    Bg1 = 0,
    Bg2 = 1,
    Bg3 = 2,
    Bg4 = 3,
    Obj = 4,
    Backdrop = 5,
}

/// Rendering
impl Ppu {
    /// Get the configured sprite size in pixels. If `size_toggle` is `false`, gets the size of
    /// small sprites, otherwise gets the size of large sprites (OAM size bit set).
    pub fn obj_size(&self, size_toggle: bool) -> (u8, u8) {
        match self.obsel >> 5 & 0b111 {
            0b000 => if !size_toggle {(8,8)} else {(16,16)},
            0b001 => if !size_toggle {(8,8)} else {(32,32)},
            0b010 => if !size_toggle {(8,8)} else {(64,64)},
            0b011 => if !size_toggle {(16,16)} else {(32,32)},
            0b100 => if !size_toggle {(16,16)} else {(64,64)},
            0b101 => if !size_toggle {(32,32)} else {(64,64)},

            0b110 => if !size_toggle {(16,32)} else {(32,64)},
            0b111 => if !size_toggle {(16,32)} else {(32,32)},
            _ => unreachable!(),
        }
    }

    /// Returns the active BG mode (0-7).
    pub fn bg_mode(&self) -> u8 { self.bgmode & 0b111 }

    /// Returns the backdrop color used as a default color (with color math applied, if enabled).
    fn backdrop_color(&self) -> Rgb {
        // TODO: Color math
        self.cgram.get_color(0)
    }

    /// Renders a "raw" pixel (not doing color math), and returns the color and the layer it came
    /// from.
    ///
    /// If `sub` is true, fetches the pixel from the subscreen. Otherwise, the main screen is used.
    fn get_raw_pixel(&mut self, subscreen: bool) -> (Rgb, Layer) {
        macro_rules! e {
            ( $e:expr ) => ( $e );
        }

        macro_rules! bglayer {
            ( 1 ) => { Layer::Bg1 };
            ( 2 ) => { Layer::Bg2 };
            ( 3 ) => { Layer::Bg3 };
            ( 4 ) => { Layer::Bg4 };
        }

        // This macro gets the current pixel from a tile with given priority in the given layer.
        // If the pixel is non-transparent, it will return its RGB value (after applying color
        // math). If it is transparent, it will do nothing (ie. the code following this macro is
        // executed).
        macro_rules! try_layer {
            ( Sprites with priority $prio:tt ) => {
                if let Some(rgb) = self.maybe_draw_sprite_pixel(e!($prio), subscreen) {
                    return (rgb, Layer::Obj);
                }
            };
            ( BG $bg:tt tiles with priority $prio:tt ) => {
                if let Some(rgb) = self.lookup_bg_color(e!($bg), e!($prio), subscreen) {
                    return (rgb, bglayer!($bg));
                }
            };
        }

        match self.bg_mode() {
            0 => {
                // I love macros <3
                try_layer!(Sprites with priority 3);
                try_layer!(BG 1 tiles with priority 1);
                try_layer!(BG 2 tiles with priority 1);
                try_layer!(Sprites with priority 2);
                try_layer!(BG 1 tiles with priority 0);
                try_layer!(BG 2 tiles with priority 0);
                try_layer!(Sprites with priority 1);
                try_layer!(BG 3 tiles with priority 1);
                try_layer!(BG 4 tiles with priority 1);
                try_layer!(Sprites with priority 0);
                try_layer!(BG 3 tiles with priority 0);
                try_layer!(BG 4 tiles with priority 0);
            }
            1 => {
                if self.bgmode & 0x08 != 0 { try_layer!(BG 3 tiles with priority 1); }
                try_layer!(Sprites with priority 3);
                try_layer!(BG 1 tiles with priority 1);
                try_layer!(BG 2 tiles with priority 1);
                try_layer!(Sprites with priority 2);
                try_layer!(BG 1 tiles with priority 0);
                try_layer!(BG 2 tiles with priority 0);
                try_layer!(Sprites with priority 1);
                if self.bgmode & 0x08 == 0 { try_layer!(BG 3 tiles with priority 1); }
                try_layer!(Sprites with priority 0);
                try_layer!(BG 3 tiles with priority 0);
            }
            2 ... 5 => {
                // FIXME Do the background priorities differ here?
                try_layer!(Sprites with priority 3);
                try_layer!(BG 1 tiles with priority 1);
                try_layer!(Sprites with priority 2);
                try_layer!(BG 2 tiles with priority 1);
                try_layer!(Sprites with priority 1);
                try_layer!(BG 1 tiles with priority 0);
                try_layer!(Sprites with priority 0);
                try_layer!(BG 2 tiles with priority 0);
            }
            6 => {
                try_layer!(Sprites with priority 3);
                try_layer!(BG 1 tiles with priority 1);
                try_layer!(Sprites with priority 2);
                try_layer!(Sprites with priority 1);
                try_layer!(BG 1 tiles with priority 0);
                try_layer!(Sprites with priority 0);
            }
            7 => panic!("NYI: BG mode 7"),
            _ => unreachable!(),
        }

        (self.backdrop_color(), Layer::Backdrop)
    }

    fn color_math_enabled(&self, layer: Layer) -> bool {
        // FIXME Take color window and CGWSEL into account
        self.cgadsub & (1 << layer as u8) != 0
    }

    /// Main rendering entry point. Renders the current pixel and returns its color. Assumes that
    /// the current pixel is on the screen.
    pub fn render_pixel(&mut self) -> Rgb {
        assert!(self.x < super::SCREEN_WIDTH as u16);
        assert!(self.scanline < super::SCREEN_HEIGHT as u16);

        if self.forced_blank() {
            return Rgb {r: 0, g: 0, b: 0};
        }

        if self.x == 0 && self.scanline == 0 {
            // Sprite overflow flags are reset "at the end of VBlank"
            // FIXME Is this correct or is the time wrong?
            self.range_over = false;
            self.time_over = false;

            trace!("New frame. BG mode {}, layers enabled: {:05b}, sprites are {:?} or {:?}",
                self.bg_mode(),
                self.tm & 0x1f,
                self.obj_size(false),
                self.obj_size(true));
        }

        if self.x == 0 {
            // Entered new scanline.
            self.collect_sprite_data_for_scanline();
        }

        let (main_pix_color, main_pix_layer) = self.get_raw_pixel(false);
        if self.color_math_enabled(main_pix_layer) {
            let math_color = if self.cgwsel & 0x02 == 0 {
                // Fixed color
                // FIXME: This is 5-bit RGB, which is totally wrong. Is it enough to do the normal
                // adjustment?
                Rgb {
                    r: self.coldata_r,
                    g: self.coldata_g,
                    b: self.coldata_b,
                }
            } else {
                // Subscreen
                self.get_raw_pixel(true).0
            };

            if self.cgadsub & 0x80 == 0 {
                // Add
                // FIXME impl Add/Sub for Rgb ?
                Rgb {
                    r: main_pix_color.r.wrapping_add(math_color.r),
                    g: main_pix_color.g.wrapping_add(math_color.g),
                    b: main_pix_color.b.wrapping_add(math_color.b),
                }
            } else {
                // Subtract
                Rgb {
                    r: main_pix_color.r.wrapping_sub(math_color.r),
                    g: main_pix_color.g.wrapping_sub(math_color.g),
                    b: main_pix_color.b.wrapping_sub(math_color.b),
                }
            }
        } else {
            // No color math
            main_pix_color
        }
    }

    /// Reads character data for a pixel and returns the palette index stored in the bitplanes.
    ///
    /// # Parameters
    /// * `bitplane_count`: Number of bitplanes (must be even)
    /// * `start_addr`: Address of the first bitplane (or the first 2)
    /// * `tile_size`: 8 or 16
    /// * `(x, y)`: Offset inside the tile (`0-7` or `0-15`, depending on the tile size)
    /// * `(vflip, hflip)`: Flip this tile vertically (top and down are flipped) or horizontally
    ///   (left and right are flipped)
    pub fn read_chr_entry(&self,
                          bitplane_count: u8,
                          start_addr: u16,
                          tile_size: u8,
                          (x, y): (u8, u8),
                          (vflip, hflip): (bool, bool)) -> u8 {
        // 2 bitplanes are stored interleaved with each other, so there can only be an even number
        debug_assert!(bitplane_count & 1 == 0, "odd bitplane count");
        debug_assert!(x <= 7 || (x <= 15 && tile_size == 16), "invalid x value: {}", x);
        debug_assert!(y <= 7 || (y <= 15 && tile_size == 16), "invalid y value: {}", y);
        debug_assert!(tile_size == 8, "non-8x8 tiles unsupported"); // FIXME support 16x16 tiles
        let bitplane_pairs = bitplane_count >> 1;

        // Flip coordinates, if necessary
        let x = if hflip { tile_size - x - 1 } else { x };
        let y = if vflip { tile_size - y - 1 } else { y };

        let mut palette_index = 0u8;
        for i in 0..bitplane_pairs {
            let bitplane_bits = self.read_2_bitplanes(
                start_addr + i as u16 * 16, // 16 Bytes per pair of bitplanes
                (x, y));
            palette_index = palette_index | (bitplane_bits << (2 * i));
        }

        palette_index
    }

    /// Reads 2 bits of the given coordinate within the bitplane's tile from 2 interleaved
    /// bitplanes.
    ///
    /// # Parameters
    /// * `bitplanes_start`: Start address of the bitplanes
    /// * `(x_off, y_off)`: Offset into the tile (`0-7`)
    fn read_2_bitplanes(&self, bitplanes_start: u16, (x_off, y_off): (u8, u8)) -> u8 {
        // Bit 0 in low bytes, bit 1 in high bytes
        let lo = self.vram[bitplanes_start + y_off as u16 * 2];
        let hi = self.vram[bitplanes_start + y_off as u16 * 2 + 1];
        // X values in a byte: 01234567
        let bit0 = (lo >> (7 - x_off)) & 1;
        let bit1 = (hi >> (7 - x_off)) & 1;

        (bit1 << 1) | bit0
    }
}
<commit_msg>Prefer NYI panic over the wrong thing<commit_after>//! Common PPU rendering code (used by sprite and BG rendering)
//!
//! # Terminology
//!
//! * **Tile**/**Character**: A tile consists of 8x8 or 16x16 pixels worth of color indices and is
//!   what makes up both sprites and backgrounds. Sprites are always made up of 8x8 tiles, while
//!   backgrounds can use 16x16 pixel tiles by setting the appropriate bit in `BGMODE ($2105)`.
//! * **Background**: A background is a big, connected layer of tiles that can (only) be moved as a
//!   unit. Depending on the background mode, between 1 and 4 BG layers can be used, each with
//!   between 4 and 256 colors.
//! * **Sprite**: A sprite is an independently movable object up to 64x64 pixels in size. Sprites
//!   always use 8x8 tiles and 16 colors, while each sprite can use a different palette. Sprites can
//!   not be rotated (rotating objects in games are either prerendered or make use of BG mode 7,
//!   which allows full matrix transformations on the layer).
//! * **Name table**/**Character table**/**Character map**: These tables store tile data: Maps of
//!   color indices to use for the tile's pixels. Sprites and all background modes except mode 7
//!   store the color indices in "bitplanes", which makes their decoding tricky: A bitplane stores 1
//!   bit for every pixel of the tile. Two bitplanes are interleaved: Bitplane 0 is stored in the
//!   low byte, while bitplane 1 is stored in the high byte.
//! * **Tile map**: Backgrounds consist of 1, 2 or 4 tile maps, each storing data for 32x32 tiles.
//!   For each tile on the background, the tile map stores the tile's priority and H/V flip bits,
//!   the palette, and the tile number. If 16x16 tiles are enabled, each entry in the tile map
//!   stores data for a 16x16 tile consisting of 4 8x8 tiles: `TILE`, `TILE+1`, `TILE+16` and
//!   `TILE+17`, where `TILE` is the stored tile number.

use super::{Ppu, Rgb};

/// An enum of all layers a pixel can come from
enum Layer {
    Bg1 = 0,
    Bg2 = 1,
    Bg3 = 2,
    Bg4 = 3,
    Obj = 4,
    Backdrop = 5,
}

/// Rendering
impl Ppu {
    /// Get the configured sprite size in pixels. If `size_toggle` is `false`, gets the size of
    /// small sprites, otherwise gets the size of large sprites (OAM size bit set).
    pub fn obj_size(&self, size_toggle: bool) -> (u8, u8) {
        match self.obsel >> 5 & 0b111 {
            0b000 => if !size_toggle {(8,8)} else {(16,16)},
            0b001 => if !size_toggle {(8,8)} else {(32,32)},
            0b010 => if !size_toggle {(8,8)} else {(64,64)},
            0b011 => if !size_toggle {(16,16)} else {(32,32)},
            0b100 => if !size_toggle {(16,16)} else {(64,64)},
            0b101 => if !size_toggle {(32,32)} else {(64,64)},

            0b110 => if !size_toggle {(16,32)} else {(32,64)},
            0b111 => if !size_toggle {(16,32)} else {(32,32)},
            _ => unreachable!(),
        }
    }

    /// Returns the active BG mode (0-7).
    pub fn bg_mode(&self) -> u8 { self.bgmode & 0b111 }

    /// Returns the backdrop color used as a default color (with color math applied, if enabled).
    fn backdrop_color(&self) -> Rgb {
        // TODO: Color math
        self.cgram.get_color(0)
    }

    /// Renders a "raw" pixel (not doing color math), and returns the color and the layer it came
    /// from.
    ///
    /// If `sub` is true, fetches the pixel from the subscreen. Otherwise, the main screen is used.
    fn get_raw_pixel(&mut self, subscreen: bool) -> (Rgb, Layer) {
        macro_rules! e {
            ( $e:expr ) => ( $e );
        }

        macro_rules! bglayer {
            ( 1 ) => { Layer::Bg1 };
            ( 2 ) => { Layer::Bg2 };
            ( 3 ) => { Layer::Bg3 };
            ( 4 ) => { Layer::Bg4 };
        }

        // This macro gets the current pixel from a tile with given priority in the given layer.
        // If the pixel is non-transparent, it will return its RGB value (after applying color
        // math). If it is transparent, it will do nothing (ie. the code following this macro is
        // executed).
        macro_rules! try_layer {
            ( Sprites with priority $prio:tt ) => {
                if let Some(rgb) = self.maybe_draw_sprite_pixel(e!($prio), subscreen) {
                    return (rgb, Layer::Obj);
                }
            };
            ( BG $bg:tt tiles with priority $prio:tt ) => {
                if let Some(rgb) = self.lookup_bg_color(e!($bg), e!($prio), subscreen) {
                    return (rgb, bglayer!($bg));
                }
            };
        }

        match self.bg_mode() {
            0 => {
                // I love macros <3
                try_layer!(Sprites with priority 3);
                try_layer!(BG 1 tiles with priority 1);
                try_layer!(BG 2 tiles with priority 1);
                try_layer!(Sprites with priority 2);
                try_layer!(BG 1 tiles with priority 0);
                try_layer!(BG 2 tiles with priority 0);
                try_layer!(Sprites with priority 1);
                try_layer!(BG 3 tiles with priority 1);
                try_layer!(BG 4 tiles with priority 1);
                try_layer!(Sprites with priority 0);
                try_layer!(BG 3 tiles with priority 0);
                try_layer!(BG 4 tiles with priority 0);
            }
            1 => {
                if self.bgmode & 0x08 != 0 { try_layer!(BG 3 tiles with priority 1); }
                try_layer!(Sprites with priority 3);
                try_layer!(BG 1 tiles with priority 1);
                try_layer!(BG 2 tiles with priority 1);
                try_layer!(Sprites with priority 2);
                try_layer!(BG 1 tiles with priority 0);
                try_layer!(BG 2 tiles with priority 0);
                try_layer!(Sprites with priority 1);
                if self.bgmode & 0x08 == 0 { try_layer!(BG 3 tiles with priority 1); }
                try_layer!(Sprites with priority 0);
                try_layer!(BG 3 tiles with priority 0);
            }
            2 ... 5 => {
                // FIXME Do the background priorities differ here?
                try_layer!(Sprites with priority 3);
                try_layer!(BG 1 tiles with priority 1);
                try_layer!(Sprites with priority 2);
                try_layer!(BG 2 tiles with priority 1);
                try_layer!(Sprites with priority 1);
                try_layer!(BG 1 tiles with priority 0);
                try_layer!(Sprites with priority 0);
                try_layer!(BG 2 tiles with priority 0);
            }
            6 => {
                try_layer!(Sprites with priority 3);
                try_layer!(BG 1 tiles with priority 1);
                try_layer!(Sprites with priority 2);
                try_layer!(Sprites with priority 1);
                try_layer!(BG 1 tiles with priority 0);
                try_layer!(Sprites with priority 0);
            }
            7 => panic!("NYI: BG mode 7"),
            _ => unreachable!(),
        }

        (self.backdrop_color(), Layer::Backdrop)
    }

    fn color_math_enabled(&self, layer: Layer) -> bool {
        // FIXME Take color window and CGWSEL into account
        self.cgadsub & (1 << layer as u8) != 0
    }

    /// Main rendering entry point. Renders the current pixel and returns its color. Assumes that
    /// the current pixel is on the screen.
    pub fn render_pixel(&mut self) -> Rgb {
        assert!(self.x < super::SCREEN_WIDTH as u16);
        assert!(self.scanline < super::SCREEN_HEIGHT as u16);

        if self.forced_blank() {
            return Rgb {r: 0, g: 0, b: 0};
        }

        if self.x == 0 && self.scanline == 0 {
            // Sprite overflow flags are reset "at the end of VBlank"
            // FIXME Is this correct or is the time wrong?
            self.range_over = false;
            self.time_over = false;

            trace!("New frame. BG mode {}, layers enabled: {:05b}, sprites are {:?} or {:?}",
                self.bg_mode(),
                self.tm & 0x1f,
                self.obj_size(false),
                self.obj_size(true));
        }

        if self.x == 0 {
            // Entered new scanline.
            self.collect_sprite_data_for_scanline();
        }

        let (main_pix_color, main_pix_layer) = self.get_raw_pixel(false);
        if self.color_math_enabled(main_pix_layer) {
            // FIXME Is color math done on 5-bit RGB? (We use adjusted 24-bit RGB, which is most
            // likely wrong!)
            let math_color = if self.cgwsel & 0x02 == 0 {
                // Fixed color
                panic!("NYI: Fixed color math");
            } else {
                // Subscreen
                self.get_raw_pixel(true).0
            };

            if self.cgadsub & 0x80 == 0 {
                // Add
                // FIXME impl Add/Sub for Rgb ?
                Rgb {
                    r: main_pix_color.r.wrapping_add(math_color.r),
                    g: main_pix_color.g.wrapping_add(math_color.g),
                    b: main_pix_color.b.wrapping_add(math_color.b),
                }
            } else {
                // Subtract
                Rgb {
                    r: main_pix_color.r.wrapping_sub(math_color.r),
                    g: main_pix_color.g.wrapping_sub(math_color.g),
                    b: main_pix_color.b.wrapping_sub(math_color.b),
                }
            }
        } else {
            // No color math
            main_pix_color
        }
    }

    /// Reads character data for a pixel and returns the palette index stored in the bitplanes.
    ///
    /// # Parameters
    /// * `bitplane_count`: Number of bitplanes (must be even)
    /// * `start_addr`: Address of the first bitplane (or the first 2)
    /// * `tile_size`: 8 or 16
    /// * `(x, y)`: Offset inside the tile (`0-7` or `0-15`, depending on the tile size)
    /// * `(vflip, hflip)`: Flip this tile vertically (top and down are flipped) or horizontally
    ///   (left and right are flipped)
    pub fn read_chr_entry(&self,
                          bitplane_count: u8,
                          start_addr: u16,
                          tile_size: u8,
                          (x, y): (u8, u8),
                          (vflip, hflip): (bool, bool)) -> u8 {
        // 2 bitplanes are stored interleaved with each other, so there can only be an even number
        debug_assert!(bitplane_count & 1 == 0, "odd bitplane count");
        debug_assert!(x <= 7 || (x <= 15 && tile_size == 16), "invalid x value: {}", x);
        debug_assert!(y <= 7 || (y <= 15 && tile_size == 16), "invalid y value: {}", y);
        debug_assert!(tile_size == 8, "non-8x8 tiles unsupported"); // FIXME support 16x16 tiles
        let bitplane_pairs = bitplane_count >> 1;

        // Flip coordinates, if necessary
        let x = if hflip { tile_size - x - 1 } else { x };
        let y = if vflip { tile_size - y - 1 } else { y };

        let mut palette_index = 0u8;
        for i in 0..bitplane_pairs {
            let bitplane_bits = self.read_2_bitplanes(
                start_addr + i as u16 * 16, // 16 Bytes per pair of bitplanes
                (x, y));
            palette_index = palette_index | (bitplane_bits << (2 * i));
        }

        palette_index
    }

    /// Reads 2 bits of the given coordinate within the bitplane's tile from 2 interleaved
    /// bitplanes.
    ///
    /// # Parameters
    /// * `bitplanes_start`: Start address of the bitplanes
    /// * `(x_off, y_off)`: Offset into the tile (`0-7`)
    fn read_2_bitplanes(&self, bitplanes_start: u16, (x_off, y_off): (u8, u8)) -> u8 {
        // Bit 0 in low bytes, bit 1 in high bytes
        let lo = self.vram[bitplanes_start + y_off as u16 * 2];
        let hi = self.vram[bitplanes_start + y_off as u16 * 2 + 1];
        // X values in a byte: 01234567
        let bit0 = (lo >> (7 - x_off)) & 1;
        let bit1 = (hi >> (7 - x_off)) & 1;

        (bit1 << 1) | bit0
    }
}
<|endoftext|>


<commit_before>fn main() {
    // Increment via closures and functions.
    fn  function            (i: i32) -> i32 { i + 1 }

    // Annotation is identical to function annotation but is optional
    // as are the `{}` wrapping the body. These nameless functions
    // are assigned to appropriately named variables.
    let closure_annotated = |i: i32| -> i32 { i + 1 };
    let closure_inferred  = |i     |          i + 1  ;

    let i = 1;
    // Call the function and closures.
    println!("function: {}", function(i));
    println!("annotated closure: {}", closure_annotated(i));
    println!("inferred closure: {}", closure_inferred(i));

    // A closure taking no arguments which returns an `i32`.
    // The return type is inferred.
    let one = || 1;
    println!("closure returning one: {}", one());

    // It is possible to capture variables from the enclosing
    // environment; something which is impossible with functions.
    let professor_x = "Charles Xavier";

    // A closure which takes no argument, returning nothing, prints
    // a variable from the enclosing scope.
    let print = || println!("Professor X's name is: {}", professor_x);

    // Call the closure.
    print();
}
<commit_msg>Remove print() closure<commit_after>fn main() {
    // Increment via closures and functions.
    fn  function            (i: i32) -> i32 { i + 1 }

    // Annotation is identical to function annotation but is optional
    // as are the `{}` wrapping the body. These nameless functions
    // are assigned to appropriately named variables.
    let closure_annotated = |i: i32| -> i32 { i + 1 };
    let closure_inferred  = |i     |          i + 1  ;

    let i = 1;
    // Call the function and closures.
    println!("function: {}", function(i));
    println!("annotated closure: {}", closure_annotated(i));
    println!("inferred closure: {}", closure_inferred(i));

    // A closure taking no arguments which returns an `i32`.
    // The return type is inferred.
    let one = || 1;
    println!("closure returning one: {}", one());

}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use font::UsedFontStyle;
use platform::font::FontHandle;
use font_context::FontContextHandleMethods;
use platform::font_list::path_from_identifier;

use freetype::freetype::{FTErrorMethods, FT_Library};
use freetype::freetype::{FT_Done_FreeType, FT_Init_FreeType};

use std::ptr;

#[deriving(Clone)]
struct FreeTypeLibraryHandle {
    ctx: FT_Library,
}

// FIXME(ksh8281) this value have to use atomic operation for counting ref
static mut font_context_ref_count: uint = 0;
static mut ft_pointer: Option<FT_Library> = None;
pub struct FontContextHandle {
    ctx: FreeTypeLibraryHandle,
}

impl Drop for FontContextHandle {
    #[fixed_stack_segment]
    fn drop(&mut self) {
        assert!(self.ctx.ctx.is_not_null());
        unsafe {
            assert!(font_context_ref_count >= 1);
            font_context_ref_count = font_context_ref_count - 1;
            if font_context_ref_count == 0 {
                FT_Done_FreeType(self.ctx.ctx);
            }
        }
    }
}

impl FontContextHandle {
    #[fixed_stack_segment]
    pub fn new() -> FontContextHandle {
        unsafe {
            match ft_pointer {
                Some(ref ctx) => {
                    font_context_ref_count = font_context_ref_count + 1;
                    FontContextHandle {
                        ctx: FreeTypeLibraryHandle { ctx: ctx.clone() },
                    }
                },
                None => {
                    let ctx: FT_Library = ptr::null();
                    let result = FT_Init_FreeType(ptr::to_unsafe_ptr(&ctx));
                    if !result.succeeded() { fail!("Unable to initialize FreeType library"); }
                    ft_pointer = Some(ctx);
                    font_context_ref_count = font_context_ref_count + 1;
                    FontContextHandle {
                        ctx: FreeTypeLibraryHandle { ctx: ctx },
                    }
                }
            }
        }
    }
}

impl FontContextHandleMethods for FontContextHandle {
    fn clone(&self) -> FontContextHandle {
        unsafe {
            font_context_ref_count = font_context_ref_count + 1;
            FontContextHandle {
                ctx: self.ctx.clone()
            }
        }
    }

    fn create_font_from_identifier(&self, name: ~str, style: UsedFontStyle)
                                -> Result<FontHandle, ()> {
        debug!("Creating font handle for {:s}", name);
        do path_from_identifier(name, &style).and_then |file_name| {
            debug!("Opening font face {:s}", file_name);
            FontHandle::new_from_file(self, file_name.to_owned(), &style)
        }
    }
}

<commit_msg>make font/platform/gfx/font_context safe<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use font::UsedFontStyle;
use platform::font::FontHandle;
use font_context::FontContextHandleMethods;
use platform::font_list::path_from_identifier;

use freetype::freetype::{FTErrorMethods, FT_Library};
use freetype::freetype::{FT_Done_FreeType, FT_Init_FreeType};

use std::ptr;
use extra::arc::Arc;

#[deriving(Clone)]
struct FreeTypeLibraryHandle {
    ctx: FT_Library,
}

pub struct FontContextHandle {
    ctx: Arc<FreeTypeLibraryHandle>,
}

impl Drop for FreeTypeLibraryHandle {
    #[fixed_stack_segment]
    fn drop(&mut self) {
        assert!(self.ctx.is_not_null());
        unsafe { FT_Done_FreeType(self.ctx) };
    }
}

impl FontContextHandle {
    #[fixed_stack_segment]
    pub fn new() -> FontContextHandle {
        unsafe {
            let ctx: FT_Library = ptr::null();
            let result = FT_Init_FreeType(ptr::to_unsafe_ptr(&ctx));
            if !result.succeeded() { fail!("Unable to initialize FreeType library"); }
            FontContextHandle {
                ctx: Arc::new(FreeTypeLibraryHandle { ctx: ctx }),
            }
        }
    }
}

impl FontContextHandleMethods for FontContextHandle {
    fn clone(&self) -> FontContextHandle {
        FontContextHandle {
            ctx: self.ctx.clone()
        }
    }

    fn create_font_from_identifier(&self, name: ~str, style: UsedFontStyle)
                                -> Result<FontHandle, ()> {
        debug!("Creating font handle for {:s}", name);
        do path_from_identifier(name, &style).and_then |file_name| {
            debug!("Opening font face {:s}", file_name);
            FontHandle::new_from_file(self, file_name.to_owned(), &style)
        }
    }
}

<|endoftext|>


<commit_before>extern crate csv;
extern crate test;
extern crate rustc_serialize;

mod distance;

use std::fs::File;
use csv::Reader;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use distance::{manhattan_dist, pearson_coef, cosine_dist};
use test::Bencher;

#[derive(RustcDecodable)]
struct User {
    id: u32,
    location: String,
    age: u32,
}

#[derive(RustcDecodable)]
struct Book {
    isbn: String,
    title: String,
    author: String,
    pub_year: u32,
    publisher: String,
}

#[derive(RustcDecodable)]
struct Rating {
    user_id: u32,
    book_isbn: String,
    rating: u32,
}

fn distance(db: &mut HashMap<u32, HashMap<String, u32>>,
            a: u32,
            b: u32,
            func: fn(&Vec<f32>, &Vec<f32>) -> f32)
            -> f32 {
    let mut vec_a = Vec::new();
    let mut vec_b = Vec::new();

    match db.get(&a) {
        Some(mut a_ratings) => {
            for (isbn_a, &rating_a) in a_ratings.iter() {
                // print!("{} ", rating_a);
                if let Some(b_ratings) = db.get(&b) {
                    if let Some(rating_b) = b_ratings.get(isbn_a) {
                        // print!("{} ", val_b);
                        vec_a.push(rating_a as f32);
                        vec_b.push(*rating_b as f32);
                    } else {
                        vec_a.push(rating_a as f32);
                        vec_b.push(0.0);
                    }
                } else {
                    panic!("b is not found!");
                }
            }
        }
        None => {}
    }

    match db.get(&b) {
        Some(mut b_ratings) => {
            for (isbn_b, &rating_b) in b_ratings.iter() {
                if let Some(a_ratings) = db.get(&a) {
                    if let Some(_) = a_ratings.get(isbn_b) {
                    } else {
                        vec_b.push(rating_b as f32);
                        vec_a.push(0.0);
                    }
                } else {
                    panic!("a is not found!");
                }
            }
        }
        None => {}
    }

    func(&vec_a, &vec_b)
}

fn init_db_reader(path: &str) -> Reader<File> {
    let rdr = csv::Reader::from_file(path).unwrap();
    rdr
}

fn load_book_ratings() {
    /*********************LOAD RATINGS*********************/
    let mut rdr = init_db_reader("./data/BX-Dump/BX-Book-Ratings.csv").has_headers(false);
    let mut ratings: HashMap<u32, HashMap<String, u32>> = HashMap::new();

    // let mut i = 0;
    for record in rdr.decode() {
        // if i > 54000 {
        //     break;
        // }
        // i += 1;
        let rating: Rating = record.unwrap();

        match ratings.entry(rating.user_id) {
            Vacant(entry) => {
                let mut user_ratings = HashMap::new();
                user_ratings.insert(rating.book_isbn, rating.rating);
                entry.insert(user_ratings);
            }
            Occupied(entry) => {
                entry.into_mut().insert(rating.book_isbn, rating.rating);
            }
        }
    }

    println!("{}", distance(&mut ratings, 11676, 278418, cosine_dist));
    println!("{}", distance(&mut ratings, 11676, 278418, manhattan_dist));
    println!("{}", distance(&mut ratings, 11676, 278418, pearson_coef));

    /*********************LOAD USERS*********************/
    /****************************************************/
}

fn main() {
    load_book_ratings();
    println!("Hello, world!");
}
<commit_msg>Movie ratings also finished<commit_after>extern crate csv;
extern crate rustc_serialize;

mod distance;

use std::fs::File;
use csv::Reader;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use distance::{manhattan_dist, pearson_coef, cosine_dist};

#[derive(RustcDecodable)]
struct User {
    id: u32,
    location: String,
    age: u32,
}

#[derive(RustcDecodable)]
struct Book {
    isbn: String,
    title: String,
    author: String,
    pub_year: u32,
    publisher: String,
}

#[derive(RustcDecodable)]
struct Rating {
    user_id: u32,
    book_isbn: String,
    rating: u32,
}

fn distance(db: &mut HashMap<u32, HashMap<String, u32>>,
            a: u32,
            b: u32,
            func: fn(&Vec<f32>, &Vec<f32>) -> f32)
            -> f32 {
    let mut vec_a = Vec::new();
    let mut vec_b = Vec::new();

    match db.get(&a) {
        Some(mut a_ratings) => {
            for (isbn_a, &rating_a) in a_ratings.iter() {
                // print!("{} ", rating_a);
                if let Some(b_ratings) = db.get(&b) {
                    if let Some(rating_b) = b_ratings.get(isbn_a) {
                        // print!("{} ", val_b);
                        vec_a.push(rating_a as f32);
                        vec_b.push(*rating_b as f32);
                    } else {
                        vec_a.push(rating_a as f32);
                        vec_b.push(0.0);
                    }
                } else {
                    panic!("b is not found!");
                }
            }
        }
        None => {}
    }

    match db.get(&b) {
        Some(mut b_ratings) => {
            for (isbn_b, &rating_b) in b_ratings.iter() {
                if let Some(a_ratings) = db.get(&a) {
                    if let Some(_) = a_ratings.get(isbn_b) {
                    } else {
                        vec_b.push(rating_b as f32);
                        vec_a.push(0.0);
                    }
                } else {
                    panic!("a is not found!");
                }
            }
        }
        None => {}
    }

    func(&vec_a, &vec_b)
}

fn init_db_reader(path: &str) -> Reader<File> {
    let rdr = csv::Reader::from_file(path).unwrap();
    rdr
}

fn book_ratings_distance() {
    /*********************LOAD RATINGS*********************/
    let mut rdr = init_db_reader("./data/BX-Dump/BX-Book-Ratings.csv").has_headers(false);
    let mut ratings: HashMap<u32, HashMap<String, u32>> = HashMap::new();

    // let mut i = 0;
    for record in rdr.decode() {
        // if i > 54000 {
        //     break;
        // }
        // i += 1;
        let rating: Rating = record.unwrap();

        match ratings.entry(rating.user_id) {
            Vacant(entry) => {
                let mut user_ratings = HashMap::new();
                user_ratings.insert(rating.book_isbn, rating.rating);
                entry.insert(user_ratings);
            }
            Occupied(entry) => {
                entry.into_mut().insert(rating.book_isbn, rating.rating);
            }
        }
    }

    println!("{}", distance(&mut ratings, 11676, 278418, cosine_dist));
    println!("{}", distance(&mut ratings, 11676, 278418, manhattan_dist));
    println!("{}", distance(&mut ratings, 11676, 278418, pearson_coef));

    /*********************LOAD USERS*********************/
    /****************************************************/
}

fn movie_ratings_distance(a: &str, b: &str) {
    /*********************LOAD RATINGS*********************/
    let mut rdr = init_db_reader("./data/Movie_Ratings_transposed.csv").has_headers(true);

    let mut vec_a = Vec::new();
    let mut vec_b = Vec::new();
    let mut catch_a = false;
    let mut catch_b = false;

    while !rdr.done() {
        // skip headers ******************************************
        loop {
            match rdr.next_bytes() {
                csv::NextField::EndOfCsv => break,
                csv::NextField::EndOfRecord => break,
                csv::NextField::Error(err) => panic!(err),
                csv::NextField::Data(_) => {}
            }
        }

        // Vector gen ********************************************
        loop {
            // User name *****************************************
            match rdr.next_bytes() {
                csv::NextField::EndOfCsv => break,
                csv::NextField::EndOfRecord => break,
                csv::NextField::Error(err) => panic!(err),
                csv::NextField::Data(r) => {
                    let st = String::from_utf8(r.to_vec()).unwrap();
                    if st == a.to_string() {
                        catch_a = true;
                    } else if st == b.to_string() {
                        catch_b = true;
                    }
                }
            }

            // Ratings *******************************************
            loop {
                match rdr.next_bytes() {
                    csv::NextField::EndOfCsv => break,
                    csv::NextField::EndOfRecord => break,
                    csv::NextField::Error(err) => panic!(err),
                    csv::NextField::Data(r) => {
                        if catch_a {
                            vec_a.push(String::from_utf8(r.to_vec())
                                           .unwrap()
                                           .parse::<f32>()
                                           .unwrap());
                        } else if catch_b {
                            vec_b.push(String::from_utf8(r.to_vec())
                                           .unwrap()
                                           .parse::<f32>()
                                           .unwrap());
                        }
                        // let val = String::from_utf8(r.to_vec()).unwrap();
                        // let val = String::from_utf8(r.to_vec())
                        //     .unwrap()
                        //     .parse::<f32>()
                        //     .unwrap();
                        // print!("{} - ", val);
                    }
                }
            }
            catch_a = false;
            catch_b = false;
        }

        // while let Some(r) = rdr.next_bytes().into_iter_result() {
        //     let st = String::from_utf8(r.unwrap().to_vec()).unwrap();
        //     print!("{} - ", st);
        // }
    }

    println!("Cosine_dist: {}", cosine_dist(&vec_a, &vec_b));
    println!("Manhattan_dist: {}", manhattan_dist(&vec_a, &vec_b));
    println!("Pearson_dist: {}", pearson_coef(&vec_a, &vec_b));
}

fn main() {
    // book_ratings_distance();
    movie_ratings_distance("Katherine", "Valerie");
    println!("Hello, world!");
}
<|endoftext|>


<commit_before>use core::prelude::*;
use platform::vga::{write_screen, LightRed, Black, Yellow, LightCyan};
use kernel::keyboard;
use kernel::keyboard::{KeyDown, Printable, Space, Escape};

#[no_mangle]
#[no_split_stack]
pub fn start()
{
	main();
}

fn main()
{
	for x in range(0u, 80)
	{
		for y in range(0u, 25)
		{
			write_screen(x, y, ' ' as u8, None, Some(LightRed));
		}
	}

	let hw = " Hello, World! ";
	for i in range(0u, hw.len())
	{
		write_screen(3+i, 3, hw[i],
		Some(match hw[i]
		{
			0x61..0x7A => LightCyan, // Lowercase ASCII
			_ => Yellow,
		}), Some(Black));
		write_screen(5+i, 5, hw[i], Some(Black), None);
	}

	'keyloop: loop
	{
		match keyboard::get_key()
		{
			KeyDown(Printable(c)) => write_screen(0, 0, c as u8, Some(Black), None),
			KeyDown(Space) => write_screen(0, 0, ' ' as u8, Some(Black), None),
			KeyDown(Escape) => break 'keyloop,
			_ => {},
		};
	}
}
<commit_msg>Do an actual halt on start's end<commit_after>use core::prelude::*;
use platform::vga::{write_screen, LightRed, Black, Yellow, LightCyan};
use kernel::keyboard;
use kernel::keyboard::{KeyDown, Printable, Space, Escape};

#[no_mangle]
#[no_split_stack]
pub fn start()
{
	main();
	loop { ::platform::cpu::halt(); }
}

fn main()
{
	for x in range(0u, 80)
	{
		for y in range(0u, 25)
		{
			write_screen(x, y, ' ' as u8, None, Some(LightRed));
		}
	}

	let hw = " Hello, World! ";
	for i in range(0u, hw.len())
	{
		write_screen(3+i, 3, hw[i],
		Some(match hw[i]
		{
			0x61..0x7A => LightCyan, // Lowercase ASCII
			_ => Yellow,
		}), Some(Black));
		write_screen(5+i, 5, hw[i], Some(Black), None);
	}

	'keyloop: loop
	{
		match keyboard::get_key()
		{
			KeyDown(Printable(c)) => write_screen(0, 0, c as u8, Some(Black), None),
			KeyDown(Space) => write_screen(0, 0, ' ' as u8, Some(Black), None),
			KeyDown(Escape) => break 'keyloop,
			_ => {},
		};
	}
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt;
use std::io::Write;

use backend::Backend;
use expression::*;
use expression::bound::Bound;
use query_builder::QueryId;
use query_source::{Queryable, QueryableByName};
use row::NamedRow;
use types::{FromSql, FromSqlRow, HasSqlType, IsNull, NotNull, Nullable, ToSql, ToSqlOutput};

impl<T, DB> HasSqlType<Nullable<T>> for DB
where
    DB: Backend + HasSqlType<T>,
    T: NotNull,
{
    fn metadata(lookup: &DB::MetadataLookup) -> DB::TypeMetadata {
        <DB as HasSqlType<T>>::metadata(lookup)
    }

    fn row_metadata(out: &mut Vec<DB::TypeMetadata>, lookup: &DB::MetadataLookup) {
        <DB as HasSqlType<T>>::row_metadata(out, lookup)
    }
}

impl<T> QueryId for Nullable<T>
where
    T: QueryId + NotNull,
{
    type QueryId = T::QueryId;

    const HAS_STATIC_QUERY_ID: bool = T::HAS_STATIC_QUERY_ID;
}

impl<T, ST, DB> FromSql<Nullable<ST>, DB> for Option<T>
where
    T: FromSql<ST, DB>,
    DB: Backend + HasSqlType<ST>,
    ST: NotNull,
{
    fn from_sql(bytes: Option<&DB::RawValue>) -> Result<Self, Box<Error + Send + Sync>> {
        match bytes {
            Some(_) => T::from_sql(bytes).map(Some),
            None => Ok(None),
        }
    }
}

impl<T, ST, DB> Queryable<Nullable<ST>, DB> for Option<T>
where
    T: Queryable<ST, DB>,
    DB: Backend + HasSqlType<ST>,
    Option<T::Row>: FromSqlRow<Nullable<ST>, DB>,
    ST: NotNull,
{
    type Row = Option<T::Row>;

    fn build(row: Self::Row) -> Self {
        row.map(T::build)
    }
}

impl<T, DB> QueryableByName<DB> for Option<T>
where
    T: QueryableByName<DB>,
    DB: Backend,
{
    fn build<R: NamedRow<DB>>(row: &R) -> Result<Self, Box<Error + Send + Sync>> {
        match T::build(row) {
            Ok(v) => Ok(Some(v)),
            Err(e) => {
                if e.is::<UnexpectedNullError>() {
                    Ok(None)
                } else {
                    Err(e)
                }
            }
        }
    }
}

impl<T, ST, DB> FromSqlRow<Nullable<ST>, DB> for Option<T>
where
    T: FromSqlRow<ST, DB>,
    DB: Backend + HasSqlType<ST>,
    ST: NotNull,
{
    const FIELDS_NEEDED: usize = T::FIELDS_NEEDED;

    fn build_from_row<R: ::row::Row<DB>>(row: &mut R) -> Result<Self, Box<Error + Send + Sync>> {
        let fields_needed = Self::FIELDS_NEEDED;
        if row.next_is_null(fields_needed) {
            row.advance(fields_needed);
            Ok(None)
        } else {
            T::build_from_row(row).map(Some)
        }
    }
}

impl<T, ST, DB> ToSql<Nullable<ST>, DB> for Option<T>
where
    T: ToSql<ST, DB>,
    DB: Backend + HasSqlType<ST>,
    ST: NotNull,
{
    fn to_sql<W: Write>(
        &self,
        out: &mut ToSqlOutput<W, DB>,
    ) -> Result<IsNull, Box<Error + Send + Sync>> {
        if let Some(ref value) = *self {
            value.to_sql(out)
        } else {
            Ok(IsNull::Yes)
        }
    }
}

impl<T, ST> AsExpression<Nullable<ST>> for Option<T>
where
    ST: NotNull,
{
    type Expression = Bound<Nullable<ST>, Self>;

    fn as_expression(self) -> Self::Expression {
        Bound::new(self)
    }
}

impl<'a, T, ST> AsExpression<Nullable<ST>> for &'a Option<T>
where
    ST: NotNull,
{
    type Expression = Bound<Nullable<ST>, Self>;

    fn as_expression(self) -> Self::Expression {
        Bound::new(self)
    }
}

#[derive(Debug)]
pub struct UnexpectedNullError {
    pub msg: String,
}

impl fmt::Display for UnexpectedNullError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.msg)
    }
}

impl Error for UnexpectedNullError {
    fn description(&self) -> &str {
        &self.msg
    }
}

#[cfg(all(test, feature = "postgres"))]
use types;
#[cfg(all(test, feature = "postgres"))]
use pg::Pg;

#[test]
#[cfg(feature = "postgres")]
fn option_to_sql() {
    type Type = types::Nullable<types::VarChar>;
    let mut bytes = ToSqlOutput::test();

    let is_null = ToSql::<Type, Pg>::to_sql(&None::<String>, &mut bytes).unwrap();
    assert_eq!(IsNull::Yes, is_null);
    assert!(bytes.is_empty());

    let is_null = ToSql::<Type, Pg>::to_sql(&Some(""), &mut bytes).unwrap();
    assert_eq!(IsNull::No, is_null);
    assert!(bytes.is_empty());

    let is_null = ToSql::<Type, Pg>::to_sql(&Some("Sean"), &mut bytes).unwrap();
    let expectd_bytes = b"Sean".to_vec();
    assert_eq!(IsNull::No, is_null);
    assert_eq!(bytes, expectd_bytes);
}
<commit_msg>Run rustfmt<commit_after>use std::error::Error;
use std::fmt;
use std::io::Write;

use backend::Backend;
use expression::*;
use expression::bound::Bound;
use query_builder::QueryId;
use query_source::{Queryable, QueryableByName};
use row::NamedRow;
use types::{FromSql, FromSqlRow, HasSqlType, IsNull, NotNull, Nullable, ToSql, ToSqlOutput};

impl<T, DB> HasSqlType<Nullable<T>> for DB
where
    DB: Backend + HasSqlType<T>,
    T: NotNull,
{
    fn metadata(lookup: &DB::MetadataLookup) -> DB::TypeMetadata {
        <DB as HasSqlType<T>>::metadata(lookup)
    }

    fn row_metadata(out: &mut Vec<DB::TypeMetadata>, lookup: &DB::MetadataLookup) {
        <DB as HasSqlType<T>>::row_metadata(out, lookup)
    }
}

impl<T> QueryId for Nullable<T>
where
    T: QueryId + NotNull,
{
    type QueryId = T::QueryId;

    const HAS_STATIC_QUERY_ID: bool = T::HAS_STATIC_QUERY_ID;
}

impl<T, ST, DB> FromSql<Nullable<ST>, DB> for Option<T>
where
    T: FromSql<ST, DB>,
    DB: Backend + HasSqlType<ST>,
    ST: NotNull,
{
    fn from_sql(bytes: Option<&DB::RawValue>) -> Result<Self, Box<Error + Send + Sync>> {
        match bytes {
            Some(_) => T::from_sql(bytes).map(Some),
            None => Ok(None),
        }
    }
}

impl<T, ST, DB> Queryable<Nullable<ST>, DB> for Option<T>
where
    T: Queryable<ST, DB>,
    DB: Backend + HasSqlType<ST>,
    Option<T::Row>: FromSqlRow<Nullable<ST>, DB>,
    ST: NotNull,
{
    type Row = Option<T::Row>;

    fn build(row: Self::Row) -> Self {
        row.map(T::build)
    }
}

impl<T, DB> QueryableByName<DB> for Option<T>
where
    T: QueryableByName<DB>,
    DB: Backend,
{
    fn build<R: NamedRow<DB>>(row: &R) -> Result<Self, Box<Error + Send + Sync>> {
        match T::build(row) {
            Ok(v) => Ok(Some(v)),
            Err(e) => if e.is::<UnexpectedNullError>() {
                Ok(None)
            } else {
                Err(e)
            },
        }
    }
}

impl<T, ST, DB> FromSqlRow<Nullable<ST>, DB> for Option<T>
where
    T: FromSqlRow<ST, DB>,
    DB: Backend + HasSqlType<ST>,
    ST: NotNull,
{
    const FIELDS_NEEDED: usize = T::FIELDS_NEEDED;

    fn build_from_row<R: ::row::Row<DB>>(row: &mut R) -> Result<Self, Box<Error + Send + Sync>> {
        let fields_needed = Self::FIELDS_NEEDED;
        if row.next_is_null(fields_needed) {
            row.advance(fields_needed);
            Ok(None)
        } else {
            T::build_from_row(row).map(Some)
        }
    }
}

impl<T, ST, DB> ToSql<Nullable<ST>, DB> for Option<T>
where
    T: ToSql<ST, DB>,
    DB: Backend + HasSqlType<ST>,
    ST: NotNull,
{
    fn to_sql<W: Write>(
        &self,
        out: &mut ToSqlOutput<W, DB>,
    ) -> Result<IsNull, Box<Error + Send + Sync>> {
        if let Some(ref value) = *self {
            value.to_sql(out)
        } else {
            Ok(IsNull::Yes)
        }
    }
}

impl<T, ST> AsExpression<Nullable<ST>> for Option<T>
where
    ST: NotNull,
{
    type Expression = Bound<Nullable<ST>, Self>;

    fn as_expression(self) -> Self::Expression {
        Bound::new(self)
    }
}

impl<'a, T, ST> AsExpression<Nullable<ST>> for &'a Option<T>
where
    ST: NotNull,
{
    type Expression = Bound<Nullable<ST>, Self>;

    fn as_expression(self) -> Self::Expression {
        Bound::new(self)
    }
}

#[derive(Debug)]
pub struct UnexpectedNullError {
    pub msg: String,
}

impl fmt::Display for UnexpectedNullError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.msg)
    }
}

impl Error for UnexpectedNullError {
    fn description(&self) -> &str {
        &self.msg
    }
}

#[cfg(all(test, feature = "postgres"))]
use types;
#[cfg(all(test, feature = "postgres"))]
use pg::Pg;

#[test]
#[cfg(feature = "postgres")]
fn option_to_sql() {
    type Type = types::Nullable<types::VarChar>;
    let mut bytes = ToSqlOutput::test();

    let is_null = ToSql::<Type, Pg>::to_sql(&None::<String>, &mut bytes).unwrap();
    assert_eq!(IsNull::Yes, is_null);
    assert!(bytes.is_empty());

    let is_null = ToSql::<Type, Pg>::to_sql(&Some(""), &mut bytes).unwrap();
    assert_eq!(IsNull::No, is_null);
    assert!(bytes.is_empty());

    let is_null = ToSql::<Type, Pg>::to_sql(&Some("Sean"), &mut bytes).unwrap();
    let expectd_bytes = b"Sean".to_vec();
    assert_eq!(IsNull::No, is_null);
    assert_eq!(bytes, expectd_bytes);
}
<|endoftext|>


<commit_before>use config::*;
use std::collections::Map;
use std::sync::RwLock;
use notify::{RecommendedWatcher, DebouncedEvent, Watcher, RecursiveMode};
use std::sync::mpsc::channel;
use std::time::Duration;

lazy_static::lazy_static! {
    static ref SETTINGS: RwLock<Config> = RwLock::new({
        let mut settings = Config::default();
        settings.merge(File::with_name("Settings.toml")).unwrap();

        settings
    });
}

fn show() {
    println!(" * Settings :: \n\x1b[31m{:?}\x1b[0m",
             SETTINGS
                 .read()
                 .unwrap()
                 .clone()
                 .try_into::<Map<String, String>>()
                 .unwrap());
}

fn watch() {
    // Create a channel to receive the events.
    let (tx, rx) = channel();

    // Automatically select the best implementation for your platform.
    // You can also access each implementation directly e.g. INotifyWatcher.
    let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2)).unwrap();

    // Add a path to be watched. All files and directories at that path and
    // below will be monitored for changes.
    watcher
        .watch("./Settings.toml", RecursiveMode::NonRecursive)
        .unwrap();

    // This is a simple loop, but you may want to use more complex logic here,
    // for example to handle I/O.
    loop {
        match rx.recv() {
            Ok(DebouncedEvent::Write(_)) => {
                println!(" * Settings.toml written; refreshing configuration ...");
                SETTINGS.write().unwrap().refresh().unwrap();
                show();
            }

            Err(e) => println!("watch error: {:?}", e),

            _ => {
                // Ignore event
            }
        }
    }
}

fn main() {
    // This is just an example of what could be done, today
    // We do want this to be built-in to config-rs at some point
    // Feel free to take a crack at a PR

    show();
    watch();
}
<commit_msg>Fix: Import HashMap instead of Map<commit_after>use config::*;
use std::collections::HashMap;
use std::sync::RwLock;
use notify::{RecommendedWatcher, DebouncedEvent, Watcher, RecursiveMode};
use std::sync::mpsc::channel;
use std::time::Duration;

lazy_static::lazy_static! {
    static ref SETTINGS: RwLock<Config> = RwLock::new({
        let mut settings = Config::default();
        settings.merge(File::with_name("Settings.toml")).unwrap();

        settings
    });
}

fn show() {
    println!(" * Settings :: \n\x1b[31m{:?}\x1b[0m",
             SETTINGS
                 .read()
                 .unwrap()
                 .clone()
                 .try_into::<HashMap<String, String>>()
                 .unwrap());
}

fn watch() {
    // Create a channel to receive the events.
    let (tx, rx) = channel();

    // Automatically select the best implementation for your platform.
    // You can also access each implementation directly e.g. INotifyWatcher.
    let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2)).unwrap();

    // Add a path to be watched. All files and directories at that path and
    // below will be monitored for changes.
    watcher
        .watch("./Settings.toml", RecursiveMode::NonRecursive)
        .unwrap();

    // This is a simple loop, but you may want to use more complex logic here,
    // for example to handle I/O.
    loop {
        match rx.recv() {
            Ok(DebouncedEvent::Write(_)) => {
                println!(" * Settings.toml written; refreshing configuration ...");
                SETTINGS.write().unwrap().refresh().unwrap();
                show();
            }

            Err(e) => println!("watch error: {:?}", e),

            _ => {
                // Ignore event
            }
        }
    }
}

fn main() {
    // This is just an example of what could be done, today
    // We do want this to be built-in to config-rs at some point
    // Feel free to take a crack at a PR

    show();
    watch();
}
<|endoftext|>