<commit_before>// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org/>

// This line shouldn't be necessary in a real project.
extern crate hyper_pkg as hyper;

use std::fs::File;
use std::path::PathBuf;
use std::pin::Pin;

use futures::prelude::*;
use http::header::{HeaderValue, AUTHORIZATION, CONTENT_TYPE};
use http_body::Body as _;
use serde::de;
use serde::Deserialize;

#[derive(Deserialize)]
#[serde(untagged)]
enum StreamMessage {
    Tweet(Tweet),
    Other(de::IgnoredAny),
}

struct Tweet {
    entities: Option<Entities>,
    id: u64,
    text: String,
    user: User,
    is_retweet: bool,
}

#[derive(Deserialize)]
struct Entities {
    user_mentions: Vec<UserMention>,
}

#[derive(Deserialize)]
struct UserMention {
    id: u64,
}

#[derive(Deserialize)]
struct User {
    id: u64,
    screen_name: String,
}

/// Represents a GET statuses/update request.
#[derive(oauth::Request)]
struct StatusUpdate<'a> {
    status: &'a str,
    in_reply_to_status_id: Option<u64>,
}

#[derive(Deserialize)]
#[serde(remote = "twitter_stream::Token")]
struct TokenDef {
    // The `getter` attribute is required to make the `Deserialize` impl use the `From` conversion,
    // even if we are not deriving `Serialize` here.
    #[serde(getter = "__")]
    consumer_key: String,
    consumer_secret: String,
    access_key: String,
    access_secret: String,
}

impl From<TokenDef> for twitter_stream::Token {
    fn from(def: TokenDef) -> twitter_stream::Token {
        twitter_stream::Token::from_parts(
            def.consumer_key,
            def.consumer_secret,
            def.access_key,
            def.access_secret,
        )
    }
}

type HttpsConnector = hyper_tls::HttpsConnector<hyper::client::HttpConnector>;

#[tokio::main]
async fn main() {
    let mut credential_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    credential_path.push("credential.json");

    let conn = HttpsConnector::new();
    let mut client = hyper::Client::builder().build::<_, hyper::Body>(conn);

    let credential = File::open(credential_path).unwrap();
    let token =
        TokenDef::deserialize(&mut serde_json::Deserializer::from_reader(credential)).unwrap();

    let mut oauth = oauth::Builder::new(token.client.as_ref(), oauth::HmacSha1);
    oauth.token(token.token.as_ref());

    // Information of the authenticated user:
    let user = verify_credentials(&oauth, &client).await;

    let mut stream = twitter_stream::Builder::new(token.as_ref())
        .track(format!("@{}", user.screen_name))
        .listen_with_client(&mut client)
        .try_flatten_stream();

    while let Some(json) = stream.next().await {
        if let Ok(StreamMessage::Tweet(tweet)) = serde_json::from_str(&json.unwrap()) {
            if !tweet.is_retweet
                && tweet.user.id != user.id
                && tweet.entities.map_or(false, |e| {
                    e.user_mentions.iter().any(|mention| mention.id == user.id)
                })
            {
                // Send a reply
                let tweeting = StatusUpdate {
                    status: &format!("@{} {}", tweet.user.screen_name, tweet.text),
                    in_reply_to_status_id: Some(tweet.id),
                }
                .send(&oauth, &client);
                tokio::spawn(tweeting);
            }
        }
    }
}

// The custom `Deserialize` impl is needed to handle Tweets with >140 characters.
// Once the Labs API is available, this impl should be unnecessary.
impl<'de> Deserialize<'de> for Tweet {
    fn deserialize<D: de::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        #[derive(Deserialize)]
        struct Prototype {
            entities: Option<Entities>,
            id: u64,
            // Add the following attribute if you want to deserialize REST API responses too.
            // #[serde(alias = "full_text")]
            text: String,
            user: User,
            extended_tweet: Option<ExtendedTweet>,
            retweeted_status: Option<de::IgnoredAny>,
        }

        #[derive(Deserialize)]
        struct ExtendedTweet {
            full_text: String,
            entities: Option<Entities>,
        }

        Prototype::deserialize(d).map(|p| {
            let (text, entities) = p
                .extended_tweet
                .map_or((p.text, p.entities), |e| (e.full_text, e.entities));
            Tweet {
                entities: entities,
                id: p.id,
                text,
                user: p.user,
                is_retweet: p.retweeted_status.is_some(),
            }
        })
    }
}

impl<'a> StatusUpdate<'a> {
    /// Performs the GET statuses/update request.
    fn send(
        &self,
        oauth: &oauth::Builder<'_, oauth::HmacSha1, &str>,
        client: &hyper::Client<HttpsConnector>,
    ) -> impl Future<Output = ()> {
        const URI: &str = "https://api.twitter.com/1.1/statuses/update.json";

        let authorization = oauth.build("POST", URI, self);
        let form = oauth::to_form_urlencoded(self);
        let req = http::Request::post(http::Uri::from_static(URI))
            .header(
                CONTENT_TYPE,
                HeaderValue::from_static("application/x-www-form-urlencoded"),
            )
            .header(AUTHORIZATION, authorization)
            .body(form.into())
            .unwrap();

        parse_response::<de::IgnoredAny>(client.request(req)).map(|_| ())
    }
}

/// Performs a GET account/verify_credentials request.
fn verify_credentials(
    oauth: &oauth::Builder<'_, oauth::HmacSha1, &str>,
    client: &hyper::Client<HttpsConnector>,
) -> impl Future<Output = User> {
    const URI: &str = "https://api.twitter.com/1.1/account/verify_credentials.json";

    let authorization = oauth.build("GET", URI, &());
    let req = http::Request::get(http::Uri::from_static(URI))
        .header(AUTHORIZATION, authorization)
        .body(Default::default())
        .unwrap();

    parse_response(client.request(req))
}

fn parse_response<T: de::DeserializeOwned>(
    res: hyper::client::ResponseFuture,
) -> impl Future<Output = T> {
    res.then(|res| {
        let mut res = res.unwrap();
        if !res.status().is_success() {
            panic!("HTTP error: {}", res.status());
        }

        stream::poll_fn(move |cx| Pin::new(&mut res).poll_data(cx))
            .try_fold(Vec::new(), |mut vec, chunk| {
                vec.extend_from_slice(&chunk);
                async { Ok(vec) }
            })
            .map(|body| serde_json::from_slice(&body.unwrap()).unwrap())
    })
}
<commit_msg>Minor cleanup<commit_after>// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org/>

// This line shouldn't be necessary in a real project.
extern crate hyper_pkg as hyper;

use std::fs::File;
use std::path::PathBuf;
use std::pin::Pin;

use futures::prelude::*;
use http::header::{HeaderValue, AUTHORIZATION, CONTENT_TYPE};
use http_body::Body as _;
use serde::de;
use serde::Deserialize;
use twitter_stream::Token;

#[derive(Deserialize)]
#[serde(untagged)]
enum StreamMessage {
    Tweet(Tweet),
    Other(de::IgnoredAny),
}

struct Tweet {
    entities: Option<Entities>,
    id: u64,
    text: String,
    user: User,
    is_retweet: bool,
}

#[derive(Deserialize)]
struct Entities {
    user_mentions: Vec<UserMention>,
}

#[derive(Deserialize)]
struct UserMention {
    id: u64,
}

#[derive(Deserialize)]
struct User {
    id: u64,
    screen_name: String,
}

/// Represents a GET statuses/update request.
#[derive(oauth::Request)]
struct StatusUpdate<'a> {
    status: &'a str,
    in_reply_to_status_id: Option<u64>,
}

#[derive(Deserialize)]
#[serde(remote = "Token")]
struct TokenDef {
    // The `getter` attribute is required to make the `Deserialize` impl use the `From` conversion,
    // even if we are not deriving `Serialize` here.
    #[serde(getter = "__")]
    consumer_key: String,
    consumer_secret: String,
    access_key: String,
    access_secret: String,
}

impl From<TokenDef> for Token {
    fn from(def: TokenDef) -> Token {
        Token::from_parts(
            def.consumer_key,
            def.consumer_secret,
            def.access_key,
            def.access_secret,
        )
    }
}

type HttpsConnector = hyper_tls::HttpsConnector<hyper::client::HttpConnector>;

#[tokio::main]
async fn main() {
    let mut credential_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    credential_path.push("credential.json");

    let conn = HttpsConnector::new();
    let mut client = hyper::Client::builder().build::<_, hyper::Body>(conn);

    let credential = File::open(credential_path).unwrap();
    let token =
        TokenDef::deserialize(&mut serde_json::Deserializer::from_reader(credential)).unwrap();

    // Information of the authenticated user:
    let user = verify_credentials(&token, &client).await;

    let mut stream = twitter_stream::Builder::new(token.as_ref())
        .track(format!("@{}", user.screen_name))
        .listen_with_client(&mut client)
        .try_flatten_stream();

    while let Some(json) = stream.next().await {
        if let Ok(StreamMessage::Tweet(tweet)) = serde_json::from_str(&json.unwrap()) {
            let mentions_me = |entities: Entities| {
                entities
                    .user_mentions
                    .iter()
                    .any(|mention| mention.id == user.id)
            };
            if !tweet.is_retweet
                && tweet.user.id != user.id
                && tweet.entities.map_or(false, mentions_me)
            {
                // Send a reply
                let tweeting = StatusUpdate {
                    status: &format!("@{} {}", tweet.user.screen_name, tweet.text),
                    in_reply_to_status_id: Some(tweet.id),
                }
                .send(&token, &client);
                tokio::spawn(tweeting);
            }
        }
    }
}

// The custom `Deserialize` impl is needed to handle Tweets with >140 characters.
// Once the Labs API is available, this impl should be unnecessary.
impl<'de> Deserialize<'de> for Tweet {
    fn deserialize<D: de::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        #[derive(Deserialize)]
        struct Prototype {
            entities: Option<Entities>,
            id: u64,
            // Add the following attribute if you want to deserialize REST API responses too.
            // #[serde(alias = "full_text")]
            text: String,
            user: User,
            extended_tweet: Option<ExtendedTweet>,
            retweeted_status: Option<de::IgnoredAny>,
        }

        #[derive(Deserialize)]
        struct ExtendedTweet {
            full_text: String,
            entities: Option<Entities>,
        }

        Prototype::deserialize(d).map(|p| {
            let (text, entities) = p
                .extended_tweet
                .map_or((p.text, p.entities), |e| (e.full_text, e.entities));
            Tweet {
                entities,
                id: p.id,
                text,
                user: p.user,
                is_retweet: p.retweeted_status.is_some(),
            }
        })
    }
}

impl<'a> StatusUpdate<'a> {
    /// Performs the GET statuses/update request.
    fn send(
        &self,
        token: &Token,
        client: &hyper::Client<HttpsConnector>,
    ) -> impl Future<Output = ()> {
        const URI: &str = "https://api.twitter.com/1.1/statuses/update.json";

        let authorization = oauth::post(URI, self, token, oauth::HmacSha1);
        let form = oauth::to_form_urlencoded(self);
        let req = http::Request::post(http::Uri::from_static(URI))
            .header(
                CONTENT_TYPE,
                HeaderValue::from_static("application/x-www-form-urlencoded"),
            )
            .header(AUTHORIZATION, authorization)
            .body(form.into())
            .unwrap();

        parse_response::<de::IgnoredAny>(client.request(req)).map(|_| ())
    }
}

/// Performs a GET account/verify_credentials request.
async fn verify_credentials(token: &Token, client: &hyper::Client<HttpsConnector>) -> User {
    const URI: &str = "https://api.twitter.com/1.1/account/verify_credentials.json";

    let authorization = oauth::get(URI, &(), token, oauth::HmacSha1);
    let req = http::Request::get(http::Uri::from_static(URI))
        .header(AUTHORIZATION, authorization)
        .body(Default::default())
        .unwrap();

    parse_response(client.request(req)).await
}

fn parse_response<T: de::DeserializeOwned>(
    res: hyper::client::ResponseFuture,
) -> impl Future<Output = T> {
    res.then(|res| {
        let mut res = res.unwrap();
        if !res.status().is_success() {
            panic!("HTTP error: {}", res.status());
        }

        stream::poll_fn(move |cx| Pin::new(&mut res).poll_data(cx))
            .try_fold(Vec::new(), |mut vec, chunk| {
                vec.extend_from_slice(&chunk);
                async { Ok(vec) }
            })
            .map(|body| serde_json::from_slice(&body.unwrap()).unwrap())
    })
}
<|endoftext|>


<commit_before>use vec_shift::Shift;
use std::str::FromStr;
use std::error::Error as StdError;
use utils::parse_quotes;

/// Defines how an operation on an `Args` method failed.
#[derive(Debug)]
pub enum Error {
    /// "END-OF-STRING", more precisely, there isn't anything to parse anymore.
    Eos,
    /// A parsing operation failed; the error in it can be of any returned from the `FromStr` trait.
    Parse(Box<StdError>),
}

type Result<T> = ::std::result::Result<T, Error>;

#[derive(Debug, Clone)]
pub struct Args {
    delimiter: String,
    delimiter_split: Vec<String>,
}

impl Args {
    pub fn new(message: &str, delimiter: &str) -> Self {
        Args {
            delimiter: delimiter.to_string(),
            delimiter_split: message.split(delimiter).map(|s| s.to_string()).collect(),
        }
    }

    /// Removes the first element, parses it to a specific type if necessary, returns.
    pub fn single<T: FromStr>(&mut self) -> Result<T> where T::Err: StdError + 'static {
        if self.delimiter_split.is_empty() {
           return Err(Error::Eos);
        }

        self.delimiter_split.shift()
            .ok_or(Error::Eos)?
            .parse::<T>()
            .map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Like [`single`], but doesn't remove the element.
    ///
    /// [`single`]: #method.single
    pub fn single_n<T: FromStr>(&mut self) -> Result<T> where T::Err: StdError + 'static {
        if self.delimiter_split.is_empty() {
           return Err(Error::Eos);
        }

        self.delimiter_split.get(0)
            .ok_or(Error::Eos)?
            .parse::<T>()
            .map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Skips if there's a first element, but also returns it.
    pub fn skip(&mut self) -> Option<String> {
        self.delimiter_split.shift()
    }

    /// Like [`skip`], but allows for multiple at once.
    ///
    /// [`skip`]: #method.skip
    pub fn skip_for(&mut self, i: u32) -> Option<Vec<String>> {
        let mut vec = Vec::with_capacity(i as usize);

        for _ in 0..i {
            vec.push(match self.delimiter_split.shift() {
                Some(x) => x,
                None => return None,
            });
        }

        Some(vec)
    }

    /// Like [`single`], but takes quotes into account.
    ///
    /// [`single`]: #method.single
    pub fn single_quoted<T: FromStr>(&mut self) -> Result<T> where T::Err: StdError + 'static  {
        parse_quotes(&self.delimiter_split.shift().ok_or(Error::Eos)?).remove(0).parse::<T>().map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Like [`single_quoted`], but doesn't remove the element.
    ///
    /// [`single_quoted`]: #method.single_quoted
    pub fn single_quoted_n<T: FromStr>(&mut self) -> Result<T> where T::Err: StdError + 'static  {
        parse_quotes(&self.delimiter_split.get(0).ok_or(Error::Eos)?).remove(0).parse::<T>().map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Like [`list`], but takes quotes into account.
    ///
    /// [`list`]: #method.list
    pub fn multiple_quoted<T: FromStr>(self) -> Result<Vec<T>> where T::Err: StdError + 'static  {
        if self.delimiter_split.is_empty() {
            return Err(Error::Eos);
        }

        parse_quotes(&self.delimiter_split.join(&self.delimiter)).into_iter().map(|s| s.parse::<T>().map_err(|e| Error::Parse(Box::new(e)))).collect()
    }

    /// Empty outs the internal vector while parsing (if necessary) and returning them
    pub fn list<T: FromStr>(self) -> Result<Vec<T>> where T::Err: StdError + 'static  {
        if self.delimiter_split.is_empty() {
            return Err(Error::Eos);
        }

        self.delimiter_split.into_iter().map(|s| s.parse::<T>().map_err(|e| Error::Parse(Box::new(e)))).collect()
    }

    /// This method is just `internal_vector.join(delimiter)`
    pub fn full(&self) -> String {
        self.delimiter_split.join(&self.delimiter)
    }
}

impl ::std::ops::Deref for Args {
    type Target = [String];

    fn deref(&self) -> &Self::Target {
        &self.delimiter_split
    }
} <commit_msg>Make args empty when no arguments are passed.<commit_after>use vec_shift::Shift;
use std::str::FromStr;
use std::error::Error as StdError;
use utils::parse_quotes;

/// Defines how an operation on an `Args` method failed.
#[derive(Debug)]
pub enum Error {
    /// "END-OF-STRING", more precisely, there isn't anything to parse anymore.
    Eos,
    /// A parsing operation failed; the error in it can be of any returned from the `FromStr` trait.
    Parse(Box<StdError>),
}

type Result<T> = ::std::result::Result<T, Error>;

#[derive(Debug, Clone)]
pub struct Args {
    delimiter: String,
    delimiter_split: Vec<String>,
}

impl Args {
    pub fn new(message: &str, delimiter: &str) -> Self {
        let split = if message.trim().is_empty() {
            Vec::new()
        } else {
            message.split(delimiter).map(|s| s.to_string()).collect()
        };

        Args {
            delimiter: delimiter.to_string(),
            delimiter_split: split,
        }
    }

    /// Removes the first element, parses it to a specific type if necessary, returns.
    pub fn single<T: FromStr>(&mut self) -> Result<T> where T::Err: StdError + 'static {
        if self.delimiter_split.is_empty() {
           return Err(Error::Eos);
        }

        self.delimiter_split.shift()
            .ok_or(Error::Eos)?
            .parse::<T>()
            .map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Like [`single`], but doesn't remove the element.
    ///
    /// [`single`]: #method.single
    pub fn single_n<T: FromStr>(&mut self) -> Result<T> where T::Err: StdError + 'static {
        if self.delimiter_split.is_empty() {
           return Err(Error::Eos);
        }

        self.delimiter_split.get(0)
            .ok_or(Error::Eos)?
            .parse::<T>()
            .map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Skips if there's a first element, but also returns it.
    pub fn skip(&mut self) -> Option<String> {
        self.delimiter_split.shift()
    }

    /// Like [`skip`], but allows for multiple at once.
    ///
    /// [`skip`]: #method.skip
    pub fn skip_for(&mut self, i: u32) -> Option<Vec<String>> {
        let mut vec = Vec::with_capacity(i as usize);

        for _ in 0..i {
            vec.push(match self.delimiter_split.shift() {
                Some(x) => x,
                None => return None,
            });
        }

        Some(vec)
    }

    /// Like [`single`], but takes quotes into account.
    ///
    /// [`single`]: #method.single
    pub fn single_quoted<T: FromStr>(&mut self) -> Result<T> where T::Err: StdError + 'static  {
        parse_quotes(&self.delimiter_split.shift().ok_or(Error::Eos)?).remove(0).parse::<T>().map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Like [`single_quoted`], but doesn't remove the element.
    ///
    /// [`single_quoted`]: #method.single_quoted
    pub fn single_quoted_n<T: FromStr>(&mut self) -> Result<T> where T::Err: StdError + 'static  {
        parse_quotes(&self.delimiter_split.get(0).ok_or(Error::Eos)?).remove(0).parse::<T>().map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Like [`list`], but takes quotes into account.
    ///
    /// [`list`]: #method.list
    pub fn multiple_quoted<T: FromStr>(self) -> Result<Vec<T>> where T::Err: StdError + 'static  {
        if self.delimiter_split.is_empty() {
            return Err(Error::Eos);
        }

        parse_quotes(&self.delimiter_split.join(&self.delimiter)).into_iter().map(|s| s.parse::<T>().map_err(|e| Error::Parse(Box::new(e)))).collect()
    }

    /// Empty outs the internal vector while parsing (if necessary) and returning them
    pub fn list<T: FromStr>(self) -> Result<Vec<T>> where T::Err: StdError + 'static  {
        if self.delimiter_split.is_empty() {
            return Err(Error::Eos);
        }

        self.delimiter_split.into_iter().map(|s| s.parse::<T>().map_err(|e| Error::Parse(Box::new(e)))).collect()
    }

    /// This method is just `internal_vector.join(delimiter)`
    pub fn full(&self) -> String {
        self.delimiter_split.join(&self.delimiter)
    }
}

impl ::std::ops::Deref for Args {
    type Target = [String];

    fn deref(&self) -> &Self::Target {
        &self.delimiter_split
    }
} <|endoftext|>


<commit_before>pub fn camel_case(name: &str) -> String {
    let mut s = String::new();
    let mut last = ' ';
    for c in name.chars().skip_while(|c| !c.is_ascii_alphanumeric()) {
        if !c.is_ascii_alphanumeric() {
            last = c;
            continue;
        }
        if (!last.is_ascii_alphanumeric() && c.is_ascii_alphanumeric())
            || (last.is_ascii_lowercase() && c.is_ascii_uppercase())
        {
            s.push(c.to_ascii_uppercase());
        } else if last.is_ascii_alphabetic() {
            s.push(c.to_ascii_lowercase());
        } else {
            s.push(c);
        }
        last = c;
    }
    s
}

pub fn snake_case(name: &str) -> String {
    sep_case(name, '_')
}

pub fn kebab_case(name: &str) -> String {
    sep_case(name, '-')
}

fn sep_case(name: &str, separator: char) -> String {
    let mut s = String::new();
    let mut last = 'A';
    for c in name.chars().skip_while(|c| !c.is_ascii_alphanumeric()) {
        if !c.is_ascii_alphanumeric() {
            last = c;
            continue;
        }
        if (!last.is_ascii_alphanumeric() && c.is_ascii_alphanumeric())
            || (last.is_ascii_lowercase() && c.is_ascii_uppercase())
        {
            s.push(separator);
        }
        s.push(c.to_ascii_lowercase());
        last = c;
    }
    s
}

pub fn type_case(name: &str) -> String {
    let s = camel_case(name);
    uppercase_first_letter(&s)
}

pub fn lower_camel_case(name: &str) -> String {
    let s = camel_case(name);
    lowercase_first_letter(&s)
}

// from http://stackoverflow.com/questions/38406793/.../38406885
fn uppercase_first_letter(s: &str) -> String {
    let mut c = s.chars();
    match c.next() {
        None => String::new(),
        Some(f) => f.to_ascii_uppercase().to_string() + c.as_str(),
    }
}

fn lowercase_first_letter(s: &str) -> String {
    let mut c = s.chars();
    match c.next() {
        None => String::new(),
        Some(f) => f.to_ascii_lowercase().to_string() + c.as_str(),
    }
}

// based on hashmap! macro from maplit crate
macro_rules! string_hashmap {
    ($($key:expr => $value:expr,)+) => { string_hashmap!($($key => $value),+) };
    ($($key:expr => $value:expr),*) => {
        {
            let mut _map = ::linked_hash_map::LinkedHashMap::new();
            $(
                _map.insert($key.to_string(), $value);
            )*
            _map
        }
    };
}

pub(crate) use string_hashmap;

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

    #[test]
    fn test_camel_case() {
        assert_eq!("FooBar", &camel_case("FooBar"));
        assert_eq!("FooBar", &camel_case("fooBar"));
        assert_eq!("FooBar", &camel_case("foo bar"));
        assert_eq!("FooBar", &camel_case("foo_bar"));
        assert_eq!("FooBar", &camel_case("_foo_bar"));
        assert_eq!("FooBar", &camel_case("åfoo_bar"));
        assert_eq!("FooBar", &camel_case("foåo_bar"));
        assert_eq!("FooBar", &camel_case("FOO_BAR"));

        assert_eq!("Foo1bar", &camel_case("Foo1bar"));
        assert_eq!("Foo2bar", &camel_case("foo_2bar"));
        assert_eq!("Foo3Bar", &camel_case("Foo3Bar"));
        assert_eq!("Foo4Bar", &camel_case("foo4_bar"));
        assert_eq!("1920x1080", &camel_case("1920x1080"));
        assert_eq!("19201080", &camel_case("1920*1080"));
    }

    #[test]
    fn test_snake_case() {
        assert_eq!("foo_bar", &snake_case("FooBar"));
        assert_eq!("foo_bar", &snake_case("fooBar"));
        assert_eq!("foo_bar", &snake_case("foo bar"));
        assert_eq!("foo_bar", &snake_case("foo_bar"));
        assert_eq!("foo_bar", &snake_case("_foo_bar"));
        assert_eq!("foo_bar", &snake_case("åfoo_bar"));
        assert_eq!("foo_bar", &snake_case("foåo_bar"));
        assert_eq!("foo_bar", &snake_case("FOO_BAR"));

        assert_eq!("foo_5bar", &snake_case("foo_5bar"));
        assert_eq!("foo6_bar", &snake_case("foo6_bar"));
        assert_eq!("1920x1080", &snake_case("1920x1080"));
        assert_eq!("1920_1080", &snake_case("1920*1080"));
    }
}
<commit_msg>shared: Fixcase functions after ascii changes<commit_after>pub fn camel_case(name: &str) -> String {
    let mut s = String::new();
    let mut last = ' ';
    for c in name.chars().skip_while(|c| !c.is_ascii_alphanumeric()) {
        if !c.is_ascii_alphanumeric() {
            last = c;
            continue;
        }
        if (last.is_ascii() && !last.is_ascii_alphanumeric() && c.is_ascii_alphanumeric())
            || (last.is_ascii_lowercase() && c.is_ascii_uppercase())
        {
            s.push(c.to_ascii_uppercase());
        } else if last.is_ascii_alphabetic() {
            s.push(c.to_ascii_lowercase());
        } else {
            s.push(c);
        }
        last = c;
    }
    s
}

pub fn snake_case(name: &str) -> String {
    sep_case(name, '_')
}

pub fn kebab_case(name: &str) -> String {
    sep_case(name, '-')
}

fn sep_case(name: &str, separator: char) -> String {
    let mut s = String::new();
    let mut last = 'A';
    for c in name.chars().skip_while(|c| !c.is_ascii_alphanumeric()) {
        if !c.is_ascii_alphanumeric() {
            last = c;
            continue;
        }
        if (last.is_ascii() && !last.is_ascii_alphanumeric() && c.is_ascii_alphanumeric())
            || (last.is_ascii_lowercase() && c.is_ascii_uppercase())
        {
            s.push(separator);
        }
        s.push(c.to_ascii_lowercase());
        last = c;
    }
    s
}

pub fn type_case(name: &str) -> String {
    let s = camel_case(name);
    uppercase_first_letter(&s)
}

pub fn lower_camel_case(name: &str) -> String {
    let s = camel_case(name);
    lowercase_first_letter(&s)
}

// from http://stackoverflow.com/questions/38406793/.../38406885
fn uppercase_first_letter(s: &str) -> String {
    let mut c = s.chars();
    match c.next() {
        None => String::new(),
        Some(f) => f.to_ascii_uppercase().to_string() + c.as_str(),
    }
}

fn lowercase_first_letter(s: &str) -> String {
    let mut c = s.chars();
    match c.next() {
        None => String::new(),
        Some(f) => f.to_ascii_lowercase().to_string() + c.as_str(),
    }
}

// based on hashmap! macro from maplit crate
macro_rules! string_hashmap {
    ($($key:expr => $value:expr,)+) => { string_hashmap!($($key => $value),+) };
    ($($key:expr => $value:expr),*) => {
        {
            let mut _map = ::linked_hash_map::LinkedHashMap::new();
            $(
                _map.insert($key.to_string(), $value);
            )*
            _map
        }
    };
}

pub(crate) use string_hashmap;

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

    #[test]
    fn test_camel_case() {
        assert_eq!("FooBar", &camel_case("FooBar"));
        assert_eq!("FooBar", &camel_case("fooBar"));
        assert_eq!("FooBar", &camel_case("foo bar"));
        assert_eq!("FooBar", &camel_case("foo_bar"));
        assert_eq!("FooBar", &camel_case("_foo_bar"));
        assert_eq!("FooBar", &camel_case("åfoo_bar"));
        assert_eq!("FooBar", &camel_case("foåo_bar"));
        assert_eq!("FooBar", &camel_case("FOO_BAR"));

        assert_eq!("Foo1bar", &camel_case("Foo1bar"));
        assert_eq!("Foo2bar", &camel_case("foo_2bar"));
        assert_eq!("Foo3Bar", &camel_case("Foo3Bar"));
        assert_eq!("Foo4Bar", &camel_case("foo4_bar"));
        assert_eq!("1920x1080", &camel_case("1920x1080"));
        assert_eq!("19201080", &camel_case("1920*1080"));
    }

    #[test]
    fn test_snake_case() {
        assert_eq!("foo_bar", &snake_case("FooBar"));
        assert_eq!("foo_bar", &snake_case("fooBar"));
        assert_eq!("foo_bar", &snake_case("foo bar"));
        assert_eq!("foo_bar", &snake_case("foo_bar"));
        assert_eq!("foo_bar", &snake_case("_foo_bar"));
        assert_eq!("foo_bar", &snake_case("åfoo_bar"));
        assert_eq!("foo_bar", &snake_case("foåo_bar"));
        assert_eq!("foo_bar", &snake_case("FOO_BAR"));

        assert_eq!("foo_5bar", &snake_case("foo_5bar"));
        assert_eq!("foo6_bar", &snake_case("foo6_bar"));
        assert_eq!("1920x1080", &snake_case("1920x1080"));
        assert_eq!("1920_1080", &snake_case("1920*1080"));
    }
}
<|endoftext|>


<commit_before>use crate::arc_or_static::ArcOrStatic;
use crate::cached_size::CachedSize;
use crate::reflect::MessageDescriptor;
use crate::reflect::ProtobufValue;
use crate::Clear;
use crate::CodedInputStream;
use crate::CodedOutputStream;
use crate::Message;
use crate::ProtobufResult;
use crate::UnknownFields;

#[derive(Debug)]
pub struct DynamicMessage {
    descriptor: ArcOrStatic<MessageDescriptor>,
    unknown_fields: UnknownFields,
    cached_size: CachedSize,
}

impl ProtobufValue for DynamicMessage {}

impl Clear for DynamicMessage {
    fn clear(&mut self) {
        unimplemented!()
    }
}

impl Message for DynamicMessage {
    fn descriptor(&self) -> &'static MessageDescriptor {
        unimplemented!()
    }

    fn is_initialized(&self) -> bool {
        unimplemented!()
    }

    fn merge_from(&mut self, _is: &mut CodedInputStream) -> ProtobufResult<()> {
        unimplemented!()
    }

    fn write_to_with_cached_sizes(&self, _os: &mut CodedOutputStream) -> ProtobufResult<()> {
        unimplemented!()
    }

    fn compute_size(&self) -> u32 {
        unimplemented!()
    }

    fn get_cached_size(&self) -> u32 {
        self.cached_size.get()
    }

    fn get_unknown_fields(&self) -> &UnknownFields {
        &self.unknown_fields
    }

    fn mut_unknown_fields(&mut self) -> &mut UnknownFields {
        &mut self.unknown_fields
    }

    fn new() -> Self
    where
        Self: Sized,
    {
        panic!("DynamicMessage cannot be constructed directly")
    }

    fn default_instance() -> &'static Self
    where
        Self: Sized,
    {
        panic!("There's no default instance for dynamic message")
    }
}
<commit_msg>Working on DynamicMessage<commit_after>use crate::arc_or_static::ArcOrStatic;
use crate::cached_size::CachedSize;
use crate::reflect::MessageDescriptor;
use crate::reflect::ProtobufValue;
use crate::reflect::ReflectValueBox;
use crate::Clear;
use crate::CodedInputStream;
use crate::CodedOutputStream;
use crate::Message;
use crate::ProtobufResult;
use crate::UnknownFields;
use std::collections::HashMap;

#[derive(Debug)]
enum DynamicFieldValue {
    Singular(ReflectValueBox),
    Repeated(Vec<ReflectValueBox>),
    Map(HashMap<ReflectValueBox, ReflectValueBox>),
}

#[derive(Debug)]
pub struct DynamicMessage {
    descriptor: ArcOrStatic<MessageDescriptor>,
    fields: HashMap<String, DynamicFieldValue>,
    unknown_fields: UnknownFields,
    cached_size: CachedSize,
}

impl ProtobufValue for DynamicMessage {}

impl Clear for DynamicMessage {
    fn clear(&mut self) {
        unimplemented!()
    }
}

impl Message for DynamicMessage {
    fn descriptor(&self) -> &'static MessageDescriptor {
        unimplemented!()
    }

    fn is_initialized(&self) -> bool {
        unimplemented!()
    }

    fn merge_from(&mut self, _is: &mut CodedInputStream) -> ProtobufResult<()> {
        unimplemented!()
    }

    fn write_to_with_cached_sizes(&self, _os: &mut CodedOutputStream) -> ProtobufResult<()> {
        unimplemented!()
    }

    fn compute_size(&self) -> u32 {
        unimplemented!()
    }

    fn get_cached_size(&self) -> u32 {
        self.cached_size.get()
    }

    fn get_unknown_fields(&self) -> &UnknownFields {
        &self.unknown_fields
    }

    fn mut_unknown_fields(&mut self) -> &mut UnknownFields {
        &mut self.unknown_fields
    }

    fn new() -> Self
    where
        Self: Sized,
    {
        panic!("DynamicMessage cannot be constructed directly")
    }

    fn default_instance() -> &'static Self
    where
        Self: Sized,
    {
        panic!("There's no default instance for dynamic message")
    }
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{Stream, StreamProducer, StreamReader};
use flac::metadata::{self, Picture, SeekPoint, VorbisComment};

use std::env;
use std::io::{self, Write};
use std::fs::File;

const USAGE: &'static str = "
Usage: metadata streaminfo [options] <filename>
       metadata comments [options] <filename>
       metadata seektable <filename>
       metadata picture [options] <filename>
       metadata --help

Options:
  --block-size       Show both the max and min block size from StreamInfo.
  --frame-size       Show both the max and min frame size from StreamInfo.
  --sample-rate      Show the sample rate from StreamInfo.
  --channels         Show the number of channels from StreamInfo.
  --bits-per-sample  Show the size in bits for each sample from StreamInfo.
  --total-samples    Show total number of samples from StreamInfo.
  --md5              Show the MD5 signature from StreamInfo.
  --vendor           Show the vendor string from VorbisComment.
  --name=NAME        Show the comments matching the `NAME` from VorbisComment.
  --export=FILE      Export VorbisComment or Picture to file.
  --index=NUMBER     Index of the current metadata type.
  -h, --help         Show this message.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_filename: String,
  cmd_streaminfo: bool,
  cmd_comments: bool,
  cmd_seektable: bool,
  cmd_picture: bool,
  flag_block_size: bool,
  flag_frame_size: bool,
  flag_sample_rate: bool,
  flag_channels: bool,
  flag_bits_per_sample: bool,
  flag_total_samples: bool,
  flag_md5: bool,
  flag_vendor: bool,
  flag_name: Option<String>,
  flag_export: Option<String>,
  flag_index: Option<usize>,
}

macro_rules! format_print (
  ($format_str: expr, $opt_str: expr, $data: expr, $no_flag: expr) => (
    {
      println!($format_str, if $no_flag {
        $opt_str
      } else {
        ""
      }, $data);
    }
  );
);

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
 where P: StreamProducer {
  let info     = stream.info();
  let no_flags = (args.flag_block_size      || args.flag_frame_size    ||
                  args.flag_sample_rate     || args.flag_channels      ||
                  args.flag_bits_per_sample || args.flag_total_samples ||
                  args.flag_md5) == false;

  if no_flags || args.flag_block_size {
    let block_size_str = if info.min_block_size == info.max_block_size {
      format!("{} samples", info.max_block_size)
    } else {
      format!("{} - {} samples", info.min_block_size, info.max_block_size)
    };

    println!("Block size: {}", block_size_str);
  }

  if no_flags || args.flag_frame_size {
    println!("Frame size: {} - {} bytes", info.min_frame_size,
                                          info.max_frame_size);
  }

  if no_flags || args.flag_sample_rate {
    format_print!("{}{} Hz", "Sample rate: ", info.sample_rate, no_flags);
  }

  if no_flags || args.flag_channels {
    format_print!("{}{}", "Number of channels: ", info.channels, no_flags);
  }

  if no_flags || args.flag_bits_per_sample {
    format_print!("{}{}", "Bits per samples: ", info.bits_per_sample,
                                                no_flags);
  }

  if no_flags || args.flag_total_samples {
    format_print!("{}{}", "Total samples: ", info.total_samples, no_flags);
  }

  if no_flags || args.flag_md5 {
    let mut md5  = String::with_capacity(32);

    for byte in &info.md5_sum {
      let hex = format!("{:02x}", byte);

      md5.push_str(&hex);
    }

    format_print!("{}{}", "MD5 sum: ", md5, no_flags);
  }
}

fn print_vorbis_comments(vorbis_comment: &VorbisComment, args: &Arguments) {
  let no_flags  = (args.flag_vendor || args.flag_name.is_some()) == false;

  if no_flags || args.flag_vendor {
    format_print!("{}{}", "Vendor string: ", vorbis_comment.vendor_string,
                                             no_flags);
  }

  if no_flags {
    let mut index = 1;

    println!("Number of Comments: {}", vorbis_comment.comments.len());

    for (name, value) in &vorbis_comment.comments {
      println!("  {}: \"{}\" = {}", index, name, value);

      index += 1;
    }
  } else {
    if let Some(ref name) = args.flag_name {
      vorbis_comment.comments.get(name)
                             .map(|value| println!("{}", value));
    }
  }
}

fn export_vorbis_comments(vorbis_comment: &VorbisComment, filename: &str)
                          -> io::Result<()> {
  let mut file = try!(File::create(filename));

  for (name, value) in &vorbis_comment.comments {
    try!(write!(file, "{}={}\n", name, value));
  }

  Ok(())
}

fn print_seek_table(seek_points: &[SeekPoint]) {
  let mut count = 0;

  println!("Number of Seek Points: {}", seek_points.len());

  for seek_point in seek_points {
    println!("Seek Point #{}", count);
    println!("  Sample number: {}", seek_point.sample_number);
    println!("  Stream offset: {}", seek_point.stream_offset);
    println!("  Frame samples: {}", seek_point.frame_samples);
    count += 1;
  }
}

fn export_picture(picture: &Picture, filename: &str) -> io::Result<()> {
  File::create(filename).and_then(|mut file| file.write_all(&picture.data))
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  let mut index = 0;
  let _index    = args.flag_index.unwrap_or(0);

  let stream = StreamReader::<File>::from_file(&args.arg_filename)
                 .expect("Couldn't parse file");

  if args.cmd_streaminfo {
    print_stream_info(&stream, &args);
  }

  for meta in stream.metadata() {
    match meta.data {
      metadata::Data::VorbisComment(ref v) => {
        if args.cmd_comments {
          if let Some(ref filename) = args.flag_export {
            export_vorbis_comments(v, filename)
              .expect("couldn't write to file")
          } else {
            print_vorbis_comments(v, &args)
          }
        }
      }
      metadata::Data::SeekTable(ref s)     => {
        if args.cmd_seektable {
          print_seek_table(s);
        }
      }
      metadata::Data::Picture(ref p)       => {
        if args.cmd_picture {
          if index != _index {
            index += 1;

            continue;
          }

          if let Some(ref filename) = args.flag_export {
            export_picture(p, filename).expect("couldn't write to file");

            break;
          }
        }
      }
      _                                    => continue,
    }
  }
}
<commit_msg>Use `format_print!` for `--block-size` option<commit_after>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{Stream, StreamProducer, StreamReader};
use flac::metadata::{self, Picture, SeekPoint, VorbisComment};

use std::env;
use std::io::{self, Write};
use std::fs::File;

const USAGE: &'static str = "
Usage: metadata streaminfo [options] <filename>
       metadata comments [options] <filename>
       metadata seektable <filename>
       metadata picture [options] <filename>
       metadata --help

Options:
  --block-size       Show both the max and min block size from StreamInfo.
  --frame-size       Show both the max and min frame size from StreamInfo.
  --sample-rate      Show the sample rate from StreamInfo.
  --channels         Show the number of channels from StreamInfo.
  --bits-per-sample  Show the size in bits for each sample from StreamInfo.
  --total-samples    Show total number of samples from StreamInfo.
  --md5              Show the MD5 signature from StreamInfo.
  --vendor           Show the vendor string from VorbisComment.
  --name=NAME        Show the comments matching the `NAME` from VorbisComment.
  --export=FILE      Export VorbisComment or Picture to file.
  --index=NUMBER     Index of the current metadata type.
  -h, --help         Show this message.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_filename: String,
  cmd_streaminfo: bool,
  cmd_comments: bool,
  cmd_seektable: bool,
  cmd_picture: bool,
  flag_block_size: bool,
  flag_frame_size: bool,
  flag_sample_rate: bool,
  flag_channels: bool,
  flag_bits_per_sample: bool,
  flag_total_samples: bool,
  flag_md5: bool,
  flag_vendor: bool,
  flag_name: Option<String>,
  flag_export: Option<String>,
  flag_index: Option<usize>,
}

macro_rules! format_print (
  ($format_str: expr, $opt_str: expr, $data: expr, $no_flag: expr) => (
    {
      println!($format_str, if $no_flag {
        $opt_str
      } else {
        ""
      }, $data);
    }
  );
);

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
 where P: StreamProducer {
  let info     = stream.info();
  let no_flags = (args.flag_block_size      || args.flag_frame_size    ||
                  args.flag_sample_rate     || args.flag_channels      ||
                  args.flag_bits_per_sample || args.flag_total_samples ||
                  args.flag_md5) == false;

  if no_flags || args.flag_block_size {
    let block_size_str = if info.min_block_size == info.max_block_size {
      format!("{} samples", info.max_block_size)
    } else {
      format!("{} - {} samples", info.min_block_size, info.max_block_size)
    };

    format_print!("{}{}", "Block size: ", block_size_str, no_flags);
  }

  if no_flags || args.flag_frame_size {
    println!("Frame size: {} - {} bytes", info.min_frame_size,
                                          info.max_frame_size);
  }

  if no_flags || args.flag_sample_rate {
    format_print!("{}{} Hz", "Sample rate: ", info.sample_rate, no_flags);
  }

  if no_flags || args.flag_channels {
    format_print!("{}{}", "Number of channels: ", info.channels, no_flags);
  }

  if no_flags || args.flag_bits_per_sample {
    format_print!("{}{}", "Bits per samples: ", info.bits_per_sample,
                                                no_flags);
  }

  if no_flags || args.flag_total_samples {
    format_print!("{}{}", "Total samples: ", info.total_samples, no_flags);
  }

  if no_flags || args.flag_md5 {
    let mut md5  = String::with_capacity(32);

    for byte in &info.md5_sum {
      let hex = format!("{:02x}", byte);

      md5.push_str(&hex);
    }

    format_print!("{}{}", "MD5 sum: ", md5, no_flags);
  }
}

fn print_vorbis_comments(vorbis_comment: &VorbisComment, args: &Arguments) {
  let no_flags  = (args.flag_vendor || args.flag_name.is_some()) == false;

  if no_flags || args.flag_vendor {
    format_print!("{}{}", "Vendor string: ", vorbis_comment.vendor_string,
                                             no_flags);
  }

  if no_flags {
    let mut index = 1;

    println!("Number of Comments: {}", vorbis_comment.comments.len());

    for (name, value) in &vorbis_comment.comments {
      println!("  {}: \"{}\" = {}", index, name, value);

      index += 1;
    }
  } else {
    if let Some(ref name) = args.flag_name {
      vorbis_comment.comments.get(name)
                             .map(|value| println!("{}", value));
    }
  }
}

fn export_vorbis_comments(vorbis_comment: &VorbisComment, filename: &str)
                          -> io::Result<()> {
  let mut file = try!(File::create(filename));

  for (name, value) in &vorbis_comment.comments {
    try!(write!(file, "{}={}\n", name, value));
  }

  Ok(())
}

fn print_seek_table(seek_points: &[SeekPoint]) {
  let mut count = 0;

  println!("Number of Seek Points: {}", seek_points.len());

  for seek_point in seek_points {
    println!("Seek Point #{}", count);
    println!("  Sample number: {}", seek_point.sample_number);
    println!("  Stream offset: {}", seek_point.stream_offset);
    println!("  Frame samples: {}", seek_point.frame_samples);
    count += 1;
  }
}

fn export_picture(picture: &Picture, filename: &str) -> io::Result<()> {
  File::create(filename).and_then(|mut file| file.write_all(&picture.data))
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  let mut index = 0;
  let _index    = args.flag_index.unwrap_or(0);

  let stream = StreamReader::<File>::from_file(&args.arg_filename)
                 .expect("Couldn't parse file");

  if args.cmd_streaminfo {
    print_stream_info(&stream, &args);
  }

  for meta in stream.metadata() {
    match meta.data {
      metadata::Data::VorbisComment(ref v) => {
        if args.cmd_comments {
          if let Some(ref filename) = args.flag_export {
            export_vorbis_comments(v, filename)
              .expect("couldn't write to file")
          } else {
            print_vorbis_comments(v, &args)
          }
        }
      }
      metadata::Data::SeekTable(ref s)     => {
        if args.cmd_seektable {
          print_seek_table(s);
        }
      }
      metadata::Data::Picture(ref p)       => {
        if args.cmd_picture {
          if index != _index {
            index += 1;

            continue;
          }

          if let Some(ref filename) = args.flag_export {
            export_picture(p, filename).expect("couldn't write to file");

            break;
          }
        }
      }
      _                                    => continue,
    }
  }
}
<|endoftext|>


<commit_before>use dovahkiin::types::*;
use index::btree::external::ExtNode;
use index::btree::external::*;
use index::btree::internal::InNode;
use index::btree::node::{write_node, Node, NodeWriteGuard};
use index::btree::remove::SubNodeStatus::InNodeEmpty;
use index::btree::{max_entry_key, BPlusTree, NodeCellRef, DeletionSetInneer};
use index::{EntryKey, Slice};
use parking_lot::RwLock;
use ram::cell::Cell;
use std::cell::RefCell;
use std::cmp::max;
use std::collections::btree_set::BTreeSet;
use std::fmt::Debug;
use std::marker::PhantomData;
use std::mem;
use std::rc::Rc;
use std::sync::atomic::AtomicUsize;
use std::sync::Arc;

pub struct TreeConstructor<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    level_guards: Vec<Rc<RefCell<NodeWriteGuard<KS, PS>>>>,
}

impl<KS, PS> TreeConstructor<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    pub fn new() -> Self {
        TreeConstructor {
            level_guards: vec![],
        }
    }

    pub fn push_extnode(&mut self, node: &NodeCellRef, first_key: EntryKey) {
        self.push(0, node, first_key);
    }

    fn push(&mut self, level: usize, node: &NodeCellRef, first_key: EntryKey) {
        let mut new_level = false;
        if self.level_guards.len() < level + 1 {
            let mut new_root_innode = InNode::<KS, PS>::new(0, max_entry_key());
            let new_root_ref = NodeCellRef::new(Node::with_internal(new_root_innode));
            self.level_guards
                .push(Rc::new(RefCell::new(write_node::<KS, PS>(&new_root_ref))));
            new_level = true;
        }
        let parent_page_ref = self.level_guards[level].clone();
        let mut parent_guard = parent_page_ref.borrow_mut();
        let cap = KS::slice_len();
        if parent_guard.len() >= cap {
            let mut new_innode = InNode::<KS, PS>::new(1, max_entry_key());
            let parent_right_bound = parent_guard.last_key().clone();
            let new_innode_head_ptr = {
                let mut parent_innode = parent_guard.innode_mut();
                parent_innode.len -= 1;
                parent_innode.right_bound = parent_right_bound.clone();
                mem::replace(
                    &mut parent_innode.ptrs.as_slice()[cap],
                    NodeCellRef::default(),
                )
            };
            new_innode.ptrs.as_slice()[0] = new_innode_head_ptr;
            new_innode.ptrs.as_slice()[1] = node.clone();
            new_innode.keys.as_slice()[0] = first_key;
            let new_node = NodeCellRef::new(Node::with_internal(new_innode));
            *parent_guard = write_node::<KS, PS>(&new_node);
            self.push(level + 1, &new_node, parent_right_bound)
        } else {
            let mut parent_innode = parent_guard.innode_mut();
            let new_len = if new_level {
                0
            } else {
                let len = parent_innode.len;
                parent_innode.keys.as_slice()[len] = first_key;
                len + 1
            };
            parent_innode.ptrs.as_slice()[new_len] = node.clone();
            parent_innode.len = new_len;
        }
    }

    pub fn root(&self) -> NodeCellRef {
        let last_ref = self.level_guards.last().unwrap().clone();
        let last_guard = last_ref.borrow();
        if last_guard.len() == 0 {
            last_guard.innode().ptrs.as_slice_immute()[0].clone()
        } else {
            last_guard.node_ref().clone()
        }
    }
}

pub fn reconstruct_from_head_page<KS, PS>(head_page_cell: Cell) -> BPlusTree<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let head_page_id = head_page_cell.id();
    let mut len = 0;
    let mut constructor = TreeConstructor::<KS, PS>::new();
    let mut prev_ref = NodeCellRef::new_none::<KS, PS>();
    let mut cell = head_page_cell;
    let mut at_end = false;
    while !at_end {
        let page = ExtNode::<KS, PS>::from_cell(&cell);
        let next_id = page.next_id;
        let prev_id = page.prev_id;
        let mut node = page.node;
        let first_key = node.keys.as_slice_immute()[0].clone();
        len += node.len;
        at_end = next_id.is_unit_id();
        node.prev = prev_ref.clone();
        if at_end {
            node.next = NodeCellRef::new_none::<KS, PS>();
        }
        let node_ref = NodeCellRef::new(Node::with_external(box node));
        let mut prev_lock = write_node::<KS, PS>(&prev_ref);
        if !prev_lock.is_none() {
            *prev_lock.right_bound_mut() = first_key.clone();
            *prev_lock.right_ref_mut().unwrap() = node_ref.clone();
        } else {
            assert_eq!(prev_id, Id::unit_id());
        }
        constructor.push_extnode(&node_ref, first_key);
        prev_ref = node_ref;
    }
    let root = constructor.root();
    BPlusTree {
        root: RwLock::new(root),
        root_versioning: NodeCellRef::new(Node::<KS, PS>::with_none()),
        head_page_id,
        len: AtomicUsize::new(len),
        deleted: Arc::new(RwLock::new(DeletionSetInneer::new())),
        marker: PhantomData,
    }
}
<commit_msg>cargo fmt<commit_after>use dovahkiin::types::*;
use index::btree::external::ExtNode;
use index::btree::external::*;
use index::btree::internal::InNode;
use index::btree::node::{write_node, Node, NodeWriteGuard};
use index::btree::remove::SubNodeStatus::InNodeEmpty;
use index::btree::{max_entry_key, BPlusTree, DeletionSetInneer, NodeCellRef};
use index::{EntryKey, Slice};
use parking_lot::RwLock;
use ram::cell::Cell;
use std::cell::RefCell;
use std::cmp::max;
use std::collections::btree_set::BTreeSet;
use std::fmt::Debug;
use std::marker::PhantomData;
use std::mem;
use std::rc::Rc;
use std::sync::atomic::AtomicUsize;
use std::sync::Arc;

pub struct TreeConstructor<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    level_guards: Vec<Rc<RefCell<NodeWriteGuard<KS, PS>>>>,
}

impl<KS, PS> TreeConstructor<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    pub fn new() -> Self {
        TreeConstructor {
            level_guards: vec![],
        }
    }

    pub fn push_extnode(&mut self, node: &NodeCellRef, first_key: EntryKey) {
        self.push(0, node, first_key);
    }

    fn push(&mut self, level: usize, node: &NodeCellRef, first_key: EntryKey) {
        let mut new_level = false;
        if self.level_guards.len() < level + 1 {
            let mut new_root_innode = InNode::<KS, PS>::new(0, max_entry_key());
            let new_root_ref = NodeCellRef::new(Node::with_internal(new_root_innode));
            self.level_guards
                .push(Rc::new(RefCell::new(write_node::<KS, PS>(&new_root_ref))));
            new_level = true;
        }
        let parent_page_ref = self.level_guards[level].clone();
        let mut parent_guard = parent_page_ref.borrow_mut();
        let cap = KS::slice_len();
        if parent_guard.len() >= cap {
            let mut new_innode = InNode::<KS, PS>::new(1, max_entry_key());
            let parent_right_bound = parent_guard.last_key().clone();
            let new_innode_head_ptr = {
                let mut parent_innode = parent_guard.innode_mut();
                parent_innode.len -= 1;
                parent_innode.right_bound = parent_right_bound.clone();
                mem::replace(
                    &mut parent_innode.ptrs.as_slice()[cap],
                    NodeCellRef::default(),
                )
            };
            new_innode.ptrs.as_slice()[0] = new_innode_head_ptr;
            new_innode.ptrs.as_slice()[1] = node.clone();
            new_innode.keys.as_slice()[0] = first_key;
            let new_node = NodeCellRef::new(Node::with_internal(new_innode));
            *parent_guard = write_node::<KS, PS>(&new_node);
            self.push(level + 1, &new_node, parent_right_bound)
        } else {
            let mut parent_innode = parent_guard.innode_mut();
            let new_len = if new_level {
                0
            } else {
                let len = parent_innode.len;
                parent_innode.keys.as_slice()[len] = first_key;
                len + 1
            };
            parent_innode.ptrs.as_slice()[new_len] = node.clone();
            parent_innode.len = new_len;
        }
    }

    pub fn root(&self) -> NodeCellRef {
        let last_ref = self.level_guards.last().unwrap().clone();
        let last_guard = last_ref.borrow();
        if last_guard.len() == 0 {
            last_guard.innode().ptrs.as_slice_immute()[0].clone()
        } else {
            last_guard.node_ref().clone()
        }
    }
}

pub fn reconstruct_from_head_page<KS, PS>(head_page_cell: Cell) -> BPlusTree<KS, PS>
where
    KS: Slice<EntryKey> + Debug + 'static,
    PS: Slice<NodeCellRef> + 'static,
{
    let head_page_id = head_page_cell.id();
    let mut len = 0;
    let mut constructor = TreeConstructor::<KS, PS>::new();
    let mut prev_ref = NodeCellRef::new_none::<KS, PS>();
    let mut cell = head_page_cell;
    let mut at_end = false;
    while !at_end {
        let page = ExtNode::<KS, PS>::from_cell(&cell);
        let next_id = page.next_id;
        let prev_id = page.prev_id;
        let mut node = page.node;
        let first_key = node.keys.as_slice_immute()[0].clone();
        len += node.len;
        at_end = next_id.is_unit_id();
        node.prev = prev_ref.clone();
        if at_end {
            node.next = NodeCellRef::new_none::<KS, PS>();
        }
        let node_ref = NodeCellRef::new(Node::with_external(box node));
        let mut prev_lock = write_node::<KS, PS>(&prev_ref);
        if !prev_lock.is_none() {
            *prev_lock.right_bound_mut() = first_key.clone();
            *prev_lock.right_ref_mut().unwrap() = node_ref.clone();
        } else {
            assert_eq!(prev_id, Id::unit_id());
        }
        constructor.push_extnode(&node_ref, first_key);
        prev_ref = node_ref;
    }
    let root = constructor.root();
    BPlusTree {
        root: RwLock::new(root),
        root_versioning: NodeCellRef::new(Node::<KS, PS>::with_none()),
        head_page_id,
        len: AtomicUsize::new(len),
        deleted: Arc::new(RwLock::new(DeletionSetInneer::new())),
        marker: PhantomData,
    }
}
<|endoftext|>


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

use std::{
    borrow::Cow,
    fmt::Debug,
    io::{Cursor, Write},
};

use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
use criterion::{black_box, Bencher, Criterion};
use rand::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

use exonum_crypto::{self, CryptoHash, Hash};
use exonum_merkledb::{
    proof_map_index::{BranchNode, ProofPath},
    StorageKey, StorageValue,
};

const CHUNK_SIZE: usize = 64;
const SEED: [u8; 16] = [100; 16];

#[derive(Debug, Clone, Copy, PartialEq)]
struct SimpleData {
    id: u16,
    class: i16,
    value: i32,
    hash: Hash,
}

impl StorageValue for SimpleData {
    fn into_bytes(self) -> Vec<u8> {
        let mut buffer = vec![0; 40];
        LittleEndian::write_u16(&mut buffer[0..2], self.id);
        LittleEndian::write_i16(&mut buffer[2..4], self.class);
        LittleEndian::write_i32(&mut buffer[4..8], self.value);
        buffer[8..].copy_from_slice(self.hash.as_ref());
        buffer
    }

    fn from_bytes(bytes: Cow<[u8]>) -> Self {
        let id = LittleEndian::read_u16(&bytes[0..2]);
        let class = LittleEndian::read_i16(&bytes[2..4]);
        let value = LittleEndian::read_i32(&bytes[4..8]);
        let hash = Hash::from_slice(&bytes[8..40]).unwrap();
        Self {
            id,
            class,
            value,
            hash,
        }
    }
}

impl CryptoHash for SimpleData {
    fn hash(&self) -> Hash {
        exonum_crypto::hash(&self.into_bytes())
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
struct CursorData {
    id: u16,
    class: i16,
    value: i32,
    hash: Hash,
}

impl StorageValue for CursorData {
    fn into_bytes(self) -> Vec<u8> {
        let mut cursor = Cursor::new(vec![0; 40]);
        cursor.write_u16::<LittleEndian>(self.id).unwrap();
        cursor.write_i16::<LittleEndian>(self.class).unwrap();
        cursor.write_i32::<LittleEndian>(self.value).unwrap();
        cursor.write_all(self.hash.as_ref()).unwrap();
        cursor.into_inner()
    }

    fn from_bytes(bytes: Cow<[u8]>) -> Self {
        let mut bytes = bytes.as_ref();
        let id = bytes.read_u16::<LittleEndian>().unwrap();
        let class = bytes.read_i16::<LittleEndian>().unwrap();
        let value = bytes.read_i32::<LittleEndian>().unwrap();
        let hash = Hash::from_slice(bytes).unwrap();
        Self {
            id,
            class,
            value,
            hash,
        }
    }
}

impl CryptoHash for CursorData {
    fn hash(&self) -> Hash {
        exonum_crypto::hash(&self.into_bytes())
    }
}

fn gen_bytes_data() -> Vec<u8> {
    let mut rng = XorShiftRng::from_seed(SEED);
    let mut v = vec![0; CHUNK_SIZE];
    rng.fill_bytes(&mut v);
    v
}

fn gen_sample_data() -> SimpleData {
    SimpleData {
        id: 1,
        class: -5,
        value: 127,
        hash: exonum_crypto::hash(&[1, 2, 3]),
    }
}

fn gen_cursor_data() -> CursorData {
    CursorData {
        id: 1,
        class: -5,
        value: 127,
        hash: exonum_crypto::hash(&[1, 2, 3]),
    }
}

fn gen_branch_node_data() -> BranchNode {
    BranchNode::empty()
}

fn bench_binary_value<F, V>(c: &mut Criterion, name: &str, f: F)
where
    F: Fn() -> V + 'static + Clone + Copy,
    V: StorageValue + Clone + PartialEq + Debug,
{
    // Checks that binary value is correct.
    let val = f();
    let bytes = val.clone().into_bytes();
    let val2 = V::from_bytes(bytes.into());
    assert_eq!(val, val2);
    // Runs benchmarks.
    c.bench_function(
        &format!("encoding/{}/into_bytes", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(f, |data| black_box(data.into_bytes()));
        },
    );
    c.bench_function(
        &format!("encoding/{}/from_bytes", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(
                || {
                    let val = f();
                    val.into_bytes()
                },
                |bytes| black_box(V::from_bytes(bytes.into())),
            );
        },
    );
    c.bench_function(
        &format!("encoding/{}/hash", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(f, |data| black_box(data.hash()));
        },
    );
}

fn bench_storage_key_concat(b: &mut Bencher) {
    b.iter_with_setup(
        || ("prefixed.key", Hash::zero(), ProofPath::new(&Hash::zero())),
        |(prefix, key, path)| {
            let mut v = vec![0; prefix.size() + key.size() + path.size()];
            let mut pos = 0;
            prefix.write(&mut v[pos..pos + prefix.size()]);
            pos += prefix.size();
            key.write(&mut v[pos..pos + key.size()]);
            pos += key.size();
            path.write(&mut v[pos..pos + path.size()]);
            black_box(v);
        },
    );
}

pub fn bench_encoding(c: &mut Criterion) {
    exonum_crypto::init();
    bench_binary_value(c, "bytes", gen_bytes_data);
    bench_binary_value(c, "simple", gen_sample_data);
    bench_binary_value(c, "cursor", gen_cursor_data);
    bench_binary_value(c, "branch_node", gen_branch_node_data);
    c.bench_function("encoding/storage_key/concat", bench_storage_key_concat);
}
<commit_msg>Improve io::Write perfomance<commit_after>// Copyright 2018 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{borrow::Cow, fmt::Debug, io::Write};

use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
use criterion::{black_box, Bencher, Criterion};
use rand::{RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;

use exonum_crypto::{self, CryptoHash, Hash};
use exonum_merkledb::{
    proof_map_index::{BranchNode, ProofPath},
    StorageKey, StorageValue,
};

const CHUNK_SIZE: usize = 64;
const SEED: [u8; 16] = [100; 16];

#[derive(Debug, Clone, Copy, PartialEq)]
struct SimpleData {
    id: u16,
    class: i16,
    value: i32,
    hash: Hash,
}

impl StorageValue for SimpleData {
    fn into_bytes(self) -> Vec<u8> {
        let mut buffer = vec![0; 40];
        LittleEndian::write_u16(&mut buffer[0..2], self.id);
        LittleEndian::write_i16(&mut buffer[2..4], self.class);
        LittleEndian::write_i32(&mut buffer[4..8], self.value);
        buffer[8..].copy_from_slice(self.hash.as_ref());
        buffer
    }

    fn from_bytes(bytes: Cow<[u8]>) -> Self {
        let id = LittleEndian::read_u16(&bytes[0..2]);
        let class = LittleEndian::read_i16(&bytes[2..4]);
        let value = LittleEndian::read_i32(&bytes[4..8]);
        let hash = Hash::from_slice(&bytes[8..40]).unwrap();
        Self {
            id,
            class,
            value,
            hash,
        }
    }
}

impl CryptoHash for SimpleData {
    fn hash(&self) -> Hash {
        exonum_crypto::hash(&self.into_bytes())
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
struct CursorData {
    id: u16,
    class: i16,
    value: i32,
    hash: Hash,
}

impl StorageValue for CursorData {
    fn into_bytes(self) -> Vec<u8> {
        let mut buf = vec![0; 40];
        let mut cursor = buf.as_mut_slice();
        cursor.write_u16::<LittleEndian>(self.id).unwrap();
        cursor.write_i16::<LittleEndian>(self.class).unwrap();
        cursor.write_i32::<LittleEndian>(self.value).unwrap();
        cursor.write_all(self.hash.as_ref()).unwrap();
        buf
    }

    fn from_bytes(bytes: Cow<[u8]>) -> Self {
        let mut bytes = bytes.as_ref();
        let id = bytes.read_u16::<LittleEndian>().unwrap();
        let class = bytes.read_i16::<LittleEndian>().unwrap();
        let value = bytes.read_i32::<LittleEndian>().unwrap();
        let hash = Hash::from_slice(bytes).unwrap();
        Self {
            id,
            class,
            value,
            hash,
        }
    }
}

impl CryptoHash for CursorData {
    fn hash(&self) -> Hash {
        exonum_crypto::hash(&self.into_bytes())
    }
}

fn gen_bytes_data() -> Vec<u8> {
    let mut rng = XorShiftRng::from_seed(SEED);
    let mut v = vec![0; CHUNK_SIZE];
    rng.fill_bytes(&mut v);
    v
}

fn gen_sample_data() -> SimpleData {
    SimpleData {
        id: 1,
        class: -5,
        value: 127,
        hash: exonum_crypto::hash(&[1, 2, 3]),
    }
}

fn gen_cursor_data() -> CursorData {
    CursorData {
        id: 1,
        class: -5,
        value: 127,
        hash: exonum_crypto::hash(&[1, 2, 3]),
    }
}

fn gen_branch_node_data() -> BranchNode {
    BranchNode::empty()
}

fn bench_binary_value<F, V>(c: &mut Criterion, name: &str, f: F)
where
    F: Fn() -> V + 'static + Clone + Copy,
    V: StorageValue + Clone + PartialEq + Debug,
{
    // Checks that binary value is correct.
    let val = f();
    let bytes = val.clone().into_bytes();
    let val2 = V::from_bytes(bytes.into());
    assert_eq!(val, val2);
    // Runs benchmarks.
    c.bench_function(
        &format!("encoding/{}/into_bytes", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(f, |data| black_box(data.into_bytes()));
        },
    );
    c.bench_function(
        &format!("encoding/{}/from_bytes", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(
                || {
                    let val = f();
                    val.into_bytes()
                },
                |bytes| black_box(V::from_bytes(bytes.into())),
            );
        },
    );
    c.bench_function(
        &format!("encoding/{}/hash", name),
        move |b: &mut Bencher| {
            b.iter_with_setup(f, |data| black_box(data.hash()));
        },
    );
}

fn bench_storage_key_concat(b: &mut Bencher) {
    b.iter_with_setup(
        || ("prefixed.key", Hash::zero(), ProofPath::new(&Hash::zero())),
        |(prefix, key, path)| {
            let mut v = vec![0; prefix.size() + key.size() + path.size()];
            let mut pos = 0;
            prefix.write(&mut v[pos..pos + prefix.size()]);
            pos += prefix.size();
            key.write(&mut v[pos..pos + key.size()]);
            pos += key.size();
            path.write(&mut v[pos..pos + path.size()]);
            black_box(v);
        },
    );
}

pub fn bench_encoding(c: &mut Criterion) {
    exonum_crypto::init();
    bench_binary_value(c, "bytes", gen_bytes_data);
    bench_binary_value(c, "simple", gen_sample_data);
    bench_binary_value(c, "cursor", gen_cursor_data);
    bench_binary_value(c, "branch_node", gen_branch_node_data);
    c.bench_function("encoding/storage_key/concat", bench_storage_key_concat);
}
<|endoftext|>


<commit_before><commit_msg>Fix window resize on deferred example (#1074)<commit_after><|endoftext|>


<commit_before>use std::collections::HashMap;

use rand;
use rand::Rng;
use rand::distributions::IndependentSample;
use itertools::Itertools;
use ndarray::prelude::*;
use ordered_float::NotNaN;

use bio::stats::{Prob, LogProb};

use io::codebook::{Codebook, FeatureID};

use model::readout::{Expressions, Counts, Miscalls, FeatureModel, NoiseModel, Xi};
use model::readout::feature_model::AbstractFeatureModel;

pub struct JointModel {
    feature_models: HashMap<FeatureID, FeatureModel>,
    noise_model: NoiseModel,
    expressions: Expressions,
    miscalls_exact: Miscalls,
    miscalls_mismatch: Miscalls,
    margin: u32,
    em_run: bool,
    rng: rand::StdRng
}

impl JointModel {
    pub fn new<'a, I: Iterator<Item=(&'a String, &'a Counts)>>(
        counts: I,
        p0: &[Prob],
        p1: &[Prob],
        codebook: &Codebook,
        window_width: u32
    ) -> Self {
        let xi = Xi::new(p0, p1);
        let mut rng = rand::StdRng::new().unwrap();

        // Generate feature models and info about not expressed features.
        let mut feature_models = HashMap::new();
        let mut not_expressed_counts = Vec::new();
        let mut not_expressed_feature_ids = Vec::new();
        for (feature, counts) in counts {
            let feature = codebook.get_id(feature);
            let rec = codebook.record(feature);
            if rec.expressed() {
                feature_models.insert(
                    feature, FeatureModel::new(feature, counts.clone(), codebook, &xi)
                );
            } else {
                not_expressed_counts.push(counts.clone());
                not_expressed_feature_ids.push(feature);
            }
        }

        let feature_count = codebook.len() + 1;

        // calculate start values (we take random numbers as start expression)
        let start_range = rand::distributions::Range::new(1, 10000);
        let mut expressions = Array1::from_iter((0..feature_count).map(
            |_| start_range.ind_sample(&mut rng)
        ));
        for &feat_id in &not_expressed_feature_ids {
            expressions[feat_id] = 0;
        }

        // Take value larger than maximum feature id as noise id.
        let noise_id = codebook.len();
        let noise_model = NoiseModel::new(
            noise_id, not_expressed_feature_ids, not_expressed_counts, codebook, &xi
        );

        let miscalls_exact = Miscalls::new(feature_count, &feature_models, &noise_model, true);
        let miscalls_mismatch = Miscalls::new(feature_count, &feature_models, &noise_model, false);

        JointModel {
            feature_models: feature_models,
            noise_model: noise_model,
            expressions: expressions,
            miscalls_exact: miscalls_exact,
            miscalls_mismatch: miscalls_mismatch,
            margin: window_width / 2,
            em_run: false,
            rng: rng
        }
    }

    /// Jointly estimate MAP using the EM algorithm.
    ///
    /// Expressions are our model parameters to estimate, miscalls are our latent variables,
    /// counts are our observed variables.
    ///
    /// # Arguments
    ///
    /// * ID of cell that is investigated (for debugging purposes).
    pub fn expectation_maximization(&mut self, cell: &str) {
        let mut feature_models: Vec<Box<&AbstractFeatureModel>> = self.feature_models.values().map(
            |m| Box::new(m as &AbstractFeatureModel)
        ).collect_vec();
        feature_models.push(Box::new(&self.noise_model));

        let n_iterations = 100;
        let change_window = 10;

        let mut last_changes = Array2::from_elem((self.expressions.len(), change_window), 0.0);

        // EM iterations
        for i in 1..n_iterations + 1 {
            debug!("EM-iteration {} of at most {}", i, n_iterations);

            // E-step: estimate miscalls
            debug!("E-step");

            // Shuffle models, such that miscalls can be drawn unbiased
            // this is necessary because there is a maximum miscall count for each feature.
            // If we would not shuffle, it would be easier for the first model to provide miscalls.
            self.rng.shuffle(&mut feature_models);
            for m in &feature_models {
                m.mle_miscalls(
                    &self.expressions,
                    &mut self.miscalls_exact,
                    &mut self.miscalls_mismatch,
                    &mut self.rng
                );
            }

            // M-step: estimate expressions that maximize the probability
            debug!("M-step");
            for m in &feature_models {
                let feature_id = m.feature_id();
                last_changes[(feature_id, feature_id % change_window)] = m.mle_expression(
                    &mut self.expressions,
                    &self.miscalls_exact,
                    &self.miscalls_mismatch
                ) as f64;
            }

            // calculate mean change per feature of last 5 steps
            let mean_changes = last_changes.mean(Axis(1));
            debug!("TYPE=EM-iteration, CELL={}, x={:?}", cell, self.expressions);
            debug!("mean changes={:?}", mean_changes);
            let convergence = *mean_changes.iter().map(
                |&c| NotNaN::new(c.abs()).unwrap()
            ).max().unwrap() <= 1.0;

            if i >= change_window && convergence {
                debug!("Convergence reached, stopping EM algorithm.");
                break;
            }
        }
        self.em_run = true;
        debug!("TYPE=EM-result, CELL={}, noise-rate={}", cell, self.noise_rate());
    }

    pub fn noise_rate(&self) -> f64 {
        assert!(self.em_run);
        self.expressions[self.expressions.len() - 1] as f64 /
        self.expressions.slice(s![..-1]).scalar_sum() as f64
    }

    pub fn likelihood(&mut self, feature_id: FeatureID, x: u32) -> LogProb {
        assert!(self.em_run);
        self.feature_model(feature_id).likelihood(
            x, &self.miscalls_exact, &self.miscalls_mismatch
        )
    }

    pub fn map_estimate(&self, feature_id: FeatureID) -> u32 {
        assert!(self.em_run);
        self.expressions[feature_id as usize]
    }

    fn feature_model(&self, feature_id: FeatureID) -> &FeatureModel {
        self.feature_models.get(&feature_id).unwrap()
    }

    /// Prior window for calculating expression PMF
    pub fn window(&self, feature_id: FeatureID) -> (u32, u32) {
        assert!(self.em_run);
        let x = self.map_estimate(feature_id);
        let xmin = self.feature_model(feature_id).min_expression(
            &self.miscalls_exact, &self.miscalls_mismatch
        );
        let xmax = x + self.margin;
        assert!(xmax >= xmin, "xmax has to be greater than xmin: xmin={}, xmax={}", xmin, xmax);
        (xmin, xmax)
    }
}
<commit_msg>Minor.<commit_after>use std::collections::HashMap;

use rand;
use rand::Rng;
use rand::distributions::IndependentSample;
use itertools::Itertools;
use ndarray::prelude::*;
use ordered_float::NotNaN;

use bio::stats::{Prob, LogProb};

use io::codebook::{Codebook, FeatureID};

use model::readout::{Expressions, Counts, Miscalls, FeatureModel, NoiseModel, Xi};
use model::readout::feature_model::AbstractFeatureModel;

pub struct JointModel {
    feature_models: HashMap<FeatureID, FeatureModel>,
    noise_model: NoiseModel,
    expressions: Expressions,
    miscalls_exact: Miscalls,
    miscalls_mismatch: Miscalls,
    margin: u32,
    em_run: bool,
    rng: rand::StdRng
}

impl JointModel {
    pub fn new<'a, I: Iterator<Item=(&'a String, &'a Counts)>>(
        counts: I,
        p0: &[Prob],
        p1: &[Prob],
        codebook: &Codebook,
        window_width: u32
    ) -> Self {
        let xi = Xi::new(p0, p1);
        let mut rng = rand::StdRng::new().unwrap();

        // Generate feature models and info about not expressed features.
        let mut feature_models = HashMap::new();
        let mut not_expressed_counts = Vec::new();
        let mut not_expressed_feature_ids = Vec::new();
        for (feature, counts) in counts {
            let feature = codebook.get_id(feature);
            let rec = codebook.record(feature);
            if rec.expressed() {
                feature_models.insert(
                    feature, FeatureModel::new(feature, counts.clone(), codebook, &xi)
                );
            } else {
                not_expressed_counts.push(counts.clone());
                not_expressed_feature_ids.push(feature);
            }
        }

        let feature_count = codebook.len() + 1;

        // calculate start values (we take random numbers as start expression)
        let start_range = rand::distributions::Range::new(1, 10000);
        let mut expressions = Array1::from_iter((0..feature_count).map(
            |_| start_range.ind_sample(&mut rng)
        ));
        for &feat_id in &not_expressed_feature_ids {
            expressions[feat_id] = 0;
        }

        // Take value larger than maximum feature id as noise id.
        let noise_id = codebook.len();
        let noise_model = NoiseModel::new(
            noise_id, not_expressed_feature_ids, not_expressed_counts, codebook, &xi
        );

        let miscalls_exact = Miscalls::new(feature_count, &feature_models, &noise_model, true);
        let miscalls_mismatch = Miscalls::new(feature_count, &feature_models, &noise_model, false);

        JointModel {
            feature_models: feature_models,
            noise_model: noise_model,
            expressions: expressions,
            miscalls_exact: miscalls_exact,
            miscalls_mismatch: miscalls_mismatch,
            margin: window_width / 2,
            em_run: false,
            rng: rng
        }
    }

    /// Jointly estimate MAP using the EM algorithm.
    ///
    /// Expressions are our model parameters to estimate, miscalls are our latent variables,
    /// counts are our observed variables.
    ///
    /// # Arguments
    ///
    /// * ID of cell that is investigated (for debugging purposes).
    pub fn expectation_maximization(&mut self, cell: &str) {
        let mut feature_models: Vec<Box<&AbstractFeatureModel>> = self.feature_models.values().map(
            |m| Box::new(m as &AbstractFeatureModel)
        ).collect_vec();
        //feature_models.push(Box::new(&self.noise_model));

        let n_iterations = 100;
        let change_window = 10;

        let mut last_changes = Array2::from_elem((self.expressions.len(), change_window), 0.0);

        // EM iterations
        for i in 1..n_iterations + 1 {
            debug!("EM-iteration {} of at most {}", i, n_iterations);

            // E-step: estimate miscalls
            debug!("E-step");

            // Shuffle models, such that miscalls can be drawn unbiased
            // this is necessary because there is a maximum miscall count for each feature.
            // If we would not shuffle, it would be easier for the first model to provide miscalls.
            self.rng.shuffle(&mut feature_models);
            for m in &feature_models {
                m.mle_miscalls(
                    &self.expressions,
                    &mut self.miscalls_exact,
                    &mut self.miscalls_mismatch,
                    &mut self.rng
                );
            }

            // M-step: estimate expressions that maximize the probability
            debug!("M-step");
            for m in &feature_models {
                let feature_id = m.feature_id();
                last_changes[(feature_id, feature_id % change_window)] = m.mle_expression(
                    &mut self.expressions,
                    &self.miscalls_exact,
                    &self.miscalls_mismatch
                ) as f64;
            }

            // calculate mean change per feature of last 5 steps
            let mean_changes = last_changes.mean(Axis(1));
            debug!("TYPE=EM-iteration, CELL={}, x={:?}", cell, self.expressions);
            debug!("mean changes={:?}", mean_changes);
            let convergence = *mean_changes.iter().map(
                |&c| NotNaN::new(c.abs()).unwrap()
            ).max().unwrap() <= 1.0;

            if i >= change_window && convergence {
                debug!("Convergence reached, stopping EM algorithm.");
                break;
            }
        }
        self.em_run = true;
        //debug!("TYPE=EM-result, CELL={}, noise-rate={}", cell, self.noise_rate());
    }

    pub fn noise_rate(&self) -> f64 {
        assert!(self.em_run);
        self.expressions[self.expressions.len() - 1] as f64 /
        self.expressions.slice(s![..-1]).scalar_sum() as f64
    }

    pub fn likelihood(&mut self, feature_id: FeatureID, x: u32) -> LogProb {
        assert!(self.em_run);
        self.feature_model(feature_id).likelihood(
            x, &self.miscalls_exact, &self.miscalls_mismatch
        )
    }

    pub fn map_estimate(&self, feature_id: FeatureID) -> u32 {
        assert!(self.em_run);
        self.expressions[feature_id as usize]
    }

    fn feature_model(&self, feature_id: FeatureID) -> &FeatureModel {
        self.feature_models.get(&feature_id).unwrap()
    }

    /// Prior window for calculating expression PMF
    pub fn window(&self, feature_id: FeatureID) -> (u32, u32) {
        assert!(self.em_run);
        let x = self.map_estimate(feature_id);
        let xmin = self.feature_model(feature_id).min_expression(
            &self.miscalls_exact, &self.miscalls_mismatch
        );
        let xmax = x + self.margin;
        assert!(xmax >= xmin, "xmax has to be greater than xmin: xmin={}, xmax={}", xmin, xmax);
        (xmin, xmax)
    }
}
<|endoftext|>


<commit_before>use orbtk::prelude::*;

use std::{thread, time};

enum Message {
    Increment,
}

#[derive(Default, AsAny)]
struct MainState {
    count: i32,
    _my_thread: Option<thread::JoinHandle<()>>,
}

impl State for MainState {
    fn init(&mut self, _registry: &mut Registry, ctx: &mut Context) {
        let entity = ctx.widget().entity();
        let message_adapter = ctx.message_adapter();

        // increments a counter and send the result as message to `MainView`.
        self._my_thread = Some(thread::spawn(move || {
            let duration = time::Duration::from_secs(1);
            loop {
                thread::sleep(duration);
                message_adapter.send_message(Message::Increment, entity);
            }
        }));
    }
    fn messages(
        &mut self,
        mut messages: MessageReader,
        _registry: &mut Registry,
        ctx: &mut Context,
    ) {
        for message in messages.read::<Message>() {
            match message {
                Message::Increment => {
                    self.count += 1;
                    MainView::text_set(&mut ctx.widget(), self.count.to_string());
                }
            }
        }
    }
}

widget!(MainView<MainState> { text: String });

impl Template for MainView {
    fn template(self, id: Entity, ctx: &mut BuildContext) -> Self {
        self.text("0").child(
            Stack::new()
                .margin(8)
                .spacing(4)
                .child(
                    TextBlock::new()
                        .text("Message counter example")
                        .style("header")
                        .build(ctx),
                )
                .child(
                    TextBlock::new()
                        .style("body")
                        .margin((0, 8, 0, 0))
                        .text(id)
                        .build(ctx),
                )
                .build(ctx),
        )
    }
}

fn main() {
    // use this only if you want to run it as web application.
    orbtk::initialize();

    Application::new()
        .window(|ctx| {
            Window::new()
                .title("OrbTk - message example")
                .position((100.0, 100.0))
                .size(420.0, 730.0)
                .child(MainView::new().build(ctx))
                .build(ctx)
        })
        .run();
}
<commit_msg>orbtk: update message example<commit_after>use orbtk::prelude::*;

use std::{thread, time};

enum Message {
    Increment,
}

// constants
pub static ID_MESSAGE: &str = "message";
pub static ID_MESSAGE_STACK: &str = "message_stack";
pub static ID_MESSAGE_TEXTBLOCK_COUNTER: &str = "message_counter";
pub static ID_MESSAGE_TEXTBLOCK_LABEL: &str = "message_counter_label";

#[derive(Default, AsAny)]
struct MainState {
    count: i32,
    _my_thread: Option<thread::JoinHandle<()>>,
}

impl State for MainState {
    fn init(&mut self, _registry: &mut Registry, ctx: &mut Context) {
        let entity = ctx.widget().entity();
        let message_adapter = ctx.message_adapter();

        // increments a counter and send the result as message to `MainView`.
        self._my_thread = Some(thread::spawn(move || {
            let duration = time::Duration::from_secs(1);
            loop {
                thread::sleep(duration);
                message_adapter.send_message(Message::Increment, entity);
            }
        }));
    }
    fn messages(
        &mut self,
        mut messages: MessageReader,
        _registry: &mut Registry,
        ctx: &mut Context,
    ) {
        for message in messages.read::<Message>() {
            match message {
                Message::Increment => {
                    self.count += 1;
                    MainView::text_set(&mut ctx.widget(), self.count.to_string());
                }
            }
        }
    }
}

widget!(MainView<MainState> { text: String });

impl Template for MainView {
    fn template(self, id: Entity, ctx: &mut BuildContext) -> Self {
        self.id(ID_MESSAGE).name(ID_MESSAGE).text("0").child(
            Stack::new()
                .id(ID_MESSAGE_STACK)
                .name(ID_MESSAGE_STACK)
                .margin(8)
                .spacing(4)
                .child(
                    TextBlock::new()
                        .id(ID_MESSAGE_TEXTBLOCK_LABEL)
                        .name(ID_MESSAGE_TEXTBLOCK_LABEL)
                        .text("Message counter example")
                        .style("header")
                        .build(ctx),
                )
                .child(
                    TextBlock::new()
                        .id(ID_MESSAGE_TEXTBLOCK_COUNTER)
                        .name(ID_MESSAGE_TEXTBLOCK_COUNTER)
                        .style("body")
                        .margin((0, 8, 0, 0))
                        .text(id)
                        .build(ctx),
                )
                .build(ctx),
        )
    }
}

fn main() {
    // use this only if you want to run it as web application.
    orbtk::initialize();

    Application::new()
        .window(|ctx| {
            Window::new()
                .title("OrbTk - message example")
                .position((100.0, 100.0))
                .size(420.0, 730.0)
                .child(MainView::new().build(ctx))
                .build(ctx)
        })
        .run();
}
<|endoftext|>


<commit_before>//! Quicksort algorithm.
//!
//! The `efficient` module contains the efficient sorting algorithm "Quicksort".
//!
//! Source: https://en.wikipedia.org/wiki/Quicksort

/// Quicksort
///
/// # Details
///
///
///
/// # Scaling
///
///
///
/// # Optimizations
///
/// None
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let mut data: Vec<i32> = vec![4, 2, 3, 1, 5];
/// sorting::efficientsorts::quick::sort(&mut data);
/// assert_eq!(vec![1, 2, 3, 4, 5], data);
/// ```
///
pub fn sort<T: PartialOrd>(array: &mut Vec<T>) {
    unimplemented!();
}
<commit_msg>Implement n = 1, n = 2 special cases<commit_after>//! Quicksort algorithm.
//!
//! The `efficient` module contains the efficient sorting algorithm "Quicksort".
//!
//! Source: https://en.wikipedia.org/wiki/Quicksort

/// Quicksort
///
/// # Details
///
///
///
/// # Scaling
///
///
///
/// # Optimizations
///
/// None
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let mut data: Vec<i32> = vec![4, 2, 3, 1, 5];
/// sorting::efficientsorts::quick::sort(&mut data);
/// assert_eq!(vec![1, 2, 3, 4, 5], data);
/// ```
///
pub fn sort<T: PartialOrd>(array: &mut Vec<T>) {
    let n = array.len();

    if n <= 1 {
        return;
    } else if n == 2 {
        if array.first() <= array.last() {
            return;
        } else {
            array.swap(0, 1);
            return;
        }
    } else {
        unimplemented!();
    }
}
<|endoftext|>