<commit_before>use crate::tick::TickUnit;
use crate::version::{Version, V_0_0_1};
use std::fmt::Display;
use std::fmt::Formatter;

pub const HEADER_LEN: usize = 128;
pub const MAGIC_U64: u64 = 0x2A54_4942_4B45_4B2A; //"*KEKBIT*" as bytes as u64
pub const LATEST: Version = V_0_0_1;

#[derive(PartialEq, Debug)]
pub enum Status {
    Open(u64),
    Timedout(u64),
    Closed(u64),
    ForcedClosed(u64),
}

impl Status {
    #[inline]
    fn status_id(&self) -> u64 {
        match self {
            Status::Open(_) => 0,
            Status::Closed(_) => 255,
            Status::ForcedClosed(_) => 512,
            Status::Timedout(_) => 1024,
        }
    }
    #[inline]
    fn from_id_and_ts(id: u64, timestamp: u64) -> Option<Status> {
        match id {
            0 => Some(Status::Open(timestamp)),
            255 => Some(Status::Closed(timestamp)),
            512 => Some(Status::ForcedClosed(timestamp)),
            1024 => Some(Status::Timedout(timestamp)),
            _ => None,
        }
    }
    #[inline]
    fn timestamp(&self) -> u64 {
        match self {
            Status::Open(ts) => *ts,
            Status::Closed(ts) => *ts,
            Status::ForcedClosed(ts) => *ts,
            Status::Timedout(ts) => *ts,
        }
    }
}

impl Display for Status {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        let res = match self {
            Status::Open(_) => "Open",
            Status::Closed(_) => "Closed",
            Status::ForcedClosed(_) => "ForcedClosed",
            Status::Timedout(_) => "Timedout",
        };
        write!(f, "{}", res)
    }
}

#[inline]
pub fn check_header(header: &[u8]) -> Result<(), String> {
    let magic = magic(header);
    if magic != MAGIC_U64 {
        return Err(format!(
            "Invalid magic header {:X}. Expected {:X}",
            magic, MAGIC_U64
        ));
    }
    let v = version(header);
    if !LATEST.is_compatible(v) {
        return Err(format!(
            "Invalid file version {}. Expected something compatible with {}",
            v, LATEST
        ));
    }
    Ok(())
}

#[inline]
pub fn write_header(
    header: &mut [u8],
    producer_id: u64,
    channel_id: u64,
    capacity: u32,
    max_msg_len: u32,
    timeout: u64,
    tick_unit: TickUnit,
) {
    let creation_time = tick_unit.nix_time();
    do_write_header(
        header,
        producer_id,
        channel_id,
        capacity,
        max_msg_len,
        timeout,
        tick_unit,
        creation_time,
    );
}
#[inline]
fn do_write_header(
    header: &mut [u8],
    producer_id: u64,
    channel_id: u64,
    capacity: u32,
    max_msg_len: u32,
    timeout: u64,
    tick_unit: TickUnit,
    creation_time: u64,
) -> usize {
    assert!(header.len() >= HEADER_LEN);
    header[0..8].clone_from_slice(&MAGIC_U64.to_le_bytes());
    let latest_v: u64 = LATEST.into();
    header[8..16].clone_from_slice(&latest_v.to_le_bytes());
    header[16..24].clone_from_slice(&producer_id.to_le_bytes());
    header[24..32].clone_from_slice(&channel_id.to_le_bytes());
    header[32..36].clone_from_slice(&capacity.to_le_bytes());
    header[36..40].clone_from_slice(&max_msg_len.to_le_bytes());
    header[40..48].clone_from_slice(&timeout.to_le_bytes());
    header[48..56].clone_from_slice(&creation_time.to_le_bytes());
    let status = Status::Open(creation_time);
    header[56..64].clone_from_slice(&status.status_id().to_le_bytes());
    header[64] = tick_unit.id();
    header[65..73].clone_from_slice(&creation_time.to_le_bytes()); //status time
    let last = 73;
    for i in last..HEADER_LEN {
        //pad up to HEADER_LEN
        header[i] = 0;
    }
    HEADER_LEN
}

#[inline]
fn read_u64(header: &[u8], offset: usize) -> u64 {
    assert!(header.len() >= HEADER_LEN);
    assert!(offset + 8 < HEADER_LEN);
    u64::from_le_bytes([
        header[offset],
        header[offset + 1],
        header[offset + 2],
        header[offset + 3],
        header[offset + 4],
        header[offset + 5],
        header[offset + 6],
        header[offset + 7],
    ])
}

#[inline]
fn read_u32(header: &[u8], offset: usize) -> u32 {
    assert!(header.len() >= HEADER_LEN);
    assert!(offset + 4 < HEADER_LEN);
    u32::from_le_bytes([
        header[offset],
        header[offset + 1],
        header[offset + 2],
        header[offset + 3],
    ])
}

#[inline]
pub fn magic(header: &[u8]) -> u64 {
    read_u64(header, 0)
}

#[inline]
pub fn version(header: &[u8]) -> Version {
    read_u64(header, 8).into()
}

#[inline]
pub fn channel_id(header: &[u8]) -> u64 {
    read_u64(header, 16)
}

#[inline]
pub fn producer_id(header: &[u8]) -> u64 {
    read_u64(header, 24)
}

#[inline]
pub fn capacity(header: &[u8]) -> u32 {
    read_u32(header, 32)
}
#[inline]
pub fn max_msg_len(header: &[u8]) -> u32 {
    read_u32(header, 36)
}
#[inline]
pub fn prod_timeout(header: &[u8]) -> u64 {
    read_u64(header, 40)
}

#[inline]
pub fn creation_time(header: &[u8]) -> u64 {
    read_u64(header, 48)
}

#[inline]
pub fn status(header: &[u8]) -> Option<Status> {
    Status::from_id_and_ts(read_u64(header, 56), status_time(header))
}

pub fn is_open(header: &[u8]) -> bool {
    let opt_status = status(header);
    opt_status.map_or(false, |st| match st {
        Status::Open(_) => true,
        _ => false,
    })
}

#[inline]
pub fn set_status(header: &mut [u8], new_status: Status) -> Result<Status, String> {
    let status_opt = status(header);
    match status_opt {
        Some(status) => match status {
            Status::Open(_) => {
                header[56..64].clone_from_slice(&new_status.status_id().to_le_bytes());
                header[64..72].clone_from_slice(&new_status.timestamp().to_le_bytes());
                Ok(new_status)
            }
            _ => Err(format!(
                "Invalid request. Transition from {} _ > {}",
                status, new_status
            )),
        },
        None => Err("Unknown curent status".to_string()),
    }
}

#[inline]
pub fn status_time(header: &[u8]) -> u64 {
    read_u64(header, 65)
}

#[inline]
pub fn tick_unit(header: &[u8]) -> TickUnit {
    TickUnit::from_id(header[64])
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn check_header() {
        let mut data = vec![0u8; HEADER_LEN];
        let producer_id: u64 = 111;
        let channel_id: u64 = 101;
        let capacity: u32 = 10001;
        let max_msg_len: u32 = 100;
        let timeout: u64 = 10000;
        let tick_unit = TickUnit::Nanos;
        let creation_time: u64 = 1111111;
        let res = do_write_header(
            &mut data,
            channel_id,
            producer_id,
            capacity,
            max_msg_len,
            timeout,
            tick_unit,
            creation_time,
        );
        assert!(res == HEADER_LEN);
        assert!(magic(&data) == MAGIC_U64);
        assert!(version(&data) == LATEST);
        assert!(super::channel_id(&data) == channel_id);
        assert!(super::producer_id(&data) == producer_id);
        assert!(super::capacity(&data) == capacity);
        assert!(super::max_msg_len(&data) == max_msg_len);
        assert!(super::creation_time(&data) == creation_time);
        assert!(super::status_time(&data) == creation_time);
        assert!(status(&data).unwrap() == Status::Open(creation_time));
        let close_ts = creation_time + 10000;
        assert!(
            super::set_status(&mut data, Status::Closed(close_ts)).unwrap()
                == Status::Closed(close_ts)
        );
    }
}
<commit_msg>Function is_open removed<commit_after>use crate::tick::TickUnit;
use crate::version::{Version, V_0_0_1};
use std::fmt::Display;
use std::fmt::Formatter;

pub const HEADER_LEN: usize = 128;
pub const MAGIC_U64: u64 = 0x2A54_4942_4B45_4B2A; //"*KEKBIT*" as bytes as u64
pub const LATEST: Version = V_0_0_1;

#[derive(PartialEq, Debug)]
pub enum Status {
    Open(u64),
    Timedout(u64),
    Closed(u64),
    ForcedClosed(u64),
}

impl Status {
    #[inline]
    fn status_id(&self) -> u64 {
        match self {
            Status::Open(_) => 0,
            Status::Closed(_) => 255,
            Status::ForcedClosed(_) => 512,
            Status::Timedout(_) => 1024,
        }
    }
    #[inline]
    fn from_id_and_ts(id: u64, timestamp: u64) -> Option<Status> {
        match id {
            0 => Some(Status::Open(timestamp)),
            255 => Some(Status::Closed(timestamp)),
            512 => Some(Status::ForcedClosed(timestamp)),
            1024 => Some(Status::Timedout(timestamp)),
            _ => None,
        }
    }
    #[inline]
    fn timestamp(&self) -> u64 {
        match self {
            Status::Open(ts) => *ts,
            Status::Closed(ts) => *ts,
            Status::ForcedClosed(ts) => *ts,
            Status::Timedout(ts) => *ts,
        }
    }
}

impl Display for Status {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        let res = match self {
            Status::Open(_) => "Open",
            Status::Closed(_) => "Closed",
            Status::ForcedClosed(_) => "ForcedClosed",
            Status::Timedout(_) => "Timedout",
        };
        write!(f, "{}", res)
    }
}

#[inline]
pub fn check_header(header: &[u8]) -> Result<(), String> {
    let magic = magic(header);
    if magic != MAGIC_U64 {
        return Err(format!(
            "Invalid magic header {:X}. Expected {:X}",
            magic, MAGIC_U64
        ));
    }
    let v = version(header);
    if !LATEST.is_compatible(v) {
        return Err(format!(
            "Invalid file version {}. Expected something compatible with {}",
            v, LATEST
        ));
    }
    Ok(())
}

#[inline]
pub fn write_header(
    header: &mut [u8],
    producer_id: u64,
    channel_id: u64,
    capacity: u32,
    max_msg_len: u32,
    timeout: u64,
    tick_unit: TickUnit,
) {
    let creation_time = tick_unit.nix_time();
    do_write_header(
        header,
        producer_id,
        channel_id,
        capacity,
        max_msg_len,
        timeout,
        tick_unit,
        creation_time,
    );
}
#[inline]
fn do_write_header(
    header: &mut [u8],
    producer_id: u64,
    channel_id: u64,
    capacity: u32,
    max_msg_len: u32,
    timeout: u64,
    tick_unit: TickUnit,
    creation_time: u64,
) -> usize {
    assert!(header.len() >= HEADER_LEN);
    header[0..8].clone_from_slice(&MAGIC_U64.to_le_bytes());
    let latest_v: u64 = LATEST.into();
    header[8..16].clone_from_slice(&latest_v.to_le_bytes());
    header[16..24].clone_from_slice(&producer_id.to_le_bytes());
    header[24..32].clone_from_slice(&channel_id.to_le_bytes());
    header[32..36].clone_from_slice(&capacity.to_le_bytes());
    header[36..40].clone_from_slice(&max_msg_len.to_le_bytes());
    header[40..48].clone_from_slice(&timeout.to_le_bytes());
    header[48..56].clone_from_slice(&creation_time.to_le_bytes());
    let status = Status::Open(creation_time);
    header[56..64].clone_from_slice(&status.status_id().to_le_bytes());
    header[64] = tick_unit.id();
    header[65..73].clone_from_slice(&creation_time.to_le_bytes()); //status time
    let last = 73;
    for i in last..HEADER_LEN {
        //pad up to HEADER_LEN
        header[i] = 0;
    }
    HEADER_LEN
}

#[inline]
fn read_u64(header: &[u8], offset: usize) -> u64 {
    assert!(header.len() >= HEADER_LEN);
    assert!(offset + 8 < HEADER_LEN);
    u64::from_le_bytes([
        header[offset],
        header[offset + 1],
        header[offset + 2],
        header[offset + 3],
        header[offset + 4],
        header[offset + 5],
        header[offset + 6],
        header[offset + 7],
    ])
}

#[inline]
fn read_u32(header: &[u8], offset: usize) -> u32 {
    assert!(header.len() >= HEADER_LEN);
    assert!(offset + 4 < HEADER_LEN);
    u32::from_le_bytes([
        header[offset],
        header[offset + 1],
        header[offset + 2],
        header[offset + 3],
    ])
}

#[inline]
pub fn magic(header: &[u8]) -> u64 {
    read_u64(header, 0)
}

#[inline]
pub fn version(header: &[u8]) -> Version {
    read_u64(header, 8).into()
}

#[inline]
pub fn channel_id(header: &[u8]) -> u64 {
    read_u64(header, 16)
}

#[inline]
pub fn producer_id(header: &[u8]) -> u64 {
    read_u64(header, 24)
}

#[inline]
pub fn capacity(header: &[u8]) -> u32 {
    read_u32(header, 32)
}
#[inline]
pub fn max_msg_len(header: &[u8]) -> u32 {
    read_u32(header, 36)
}
#[inline]
pub fn prod_timeout(header: &[u8]) -> u64 {
    read_u64(header, 40)
}

#[inline]
pub fn creation_time(header: &[u8]) -> u64 {
    read_u64(header, 48)
}

#[inline]
pub fn status(header: &[u8]) -> Option<Status> {
    Status::from_id_and_ts(read_u64(header, 56), status_time(header))
}

#[inline]
pub fn set_status(header: &mut [u8], new_status: Status) -> Result<Status, String> {
    let status_opt = status(header);
    match status_opt {
        Some(status) => match status {
            Status::Open(_) => {
                header[56..64].clone_from_slice(&new_status.status_id().to_le_bytes());
                header[64..72].clone_from_slice(&new_status.timestamp().to_le_bytes());
                Ok(new_status)
            }
            _ => Err(format!(
                "Invalid request. Transition from {} _ > {}",
                status, new_status
            )),
        },
        None => Err("Unknown curent status".to_string()),
    }
}

#[inline]
pub fn status_time(header: &[u8]) -> u64 {
    read_u64(header, 65)
}

#[inline]
pub fn tick_unit(header: &[u8]) -> TickUnit {
    TickUnit::from_id(header[64])
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn check_header() {
        let mut data = vec![0u8; HEADER_LEN];
        let producer_id: u64 = 111;
        let channel_id: u64 = 101;
        let capacity: u32 = 10001;
        let max_msg_len: u32 = 100;
        let timeout: u64 = 10000;
        let tick_unit = TickUnit::Nanos;
        let creation_time: u64 = 1111111;
        let res = do_write_header(
            &mut data,
            channel_id,
            producer_id,
            capacity,
            max_msg_len,
            timeout,
            tick_unit,
            creation_time,
        );
        assert!(res == HEADER_LEN);
        assert!(magic(&data) == MAGIC_U64);
        assert!(version(&data) == LATEST);
        assert!(super::channel_id(&data) == channel_id);
        assert!(super::producer_id(&data) == producer_id);
        assert!(super::capacity(&data) == capacity);
        assert!(super::max_msg_len(&data) == max_msg_len);
        assert!(super::creation_time(&data) == creation_time);
        assert!(super::status_time(&data) == creation_time);
        assert!(status(&data).unwrap() == Status::Open(creation_time));
        let close_ts = creation_time + 10000;
        assert!(
            super::set_status(&mut data, Status::Closed(close_ts)).unwrap()
                == Status::Closed(close_ts)
        );
    }
}
<|endoftext|>


<commit_before>use std::path::Path;
use std::io;
use std::fs::File;
use std::convert;

use serde_json;

use gerrit;
use spark;

#[derive(Debug, Clone, Serialize, Deserialize)]
struct User {
    spark_person_id: spark::PersonId,
    email: spark::Email,
    enabled: bool,
}

impl User {
    fn new(person_id: spark::PersonId, email: spark::Email) -> User {
        User {
            spark_person_id: person_id,
            email: email,
            enabled: true,
        }
    }
}

/// Describes a state of the bot
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Bot {
    users: Vec<User>,
}

#[derive(Debug)]
pub enum BotError {
    Io(io::Error),
    Serialization(serde_json::Error),
}

impl convert::From<io::Error> for BotError {
    fn from(err: io::Error) -> BotError {
        BotError::Io(err)
    }
}

impl convert::From<serde_json::Error> for BotError {
    fn from(err: serde_json::Error) -> BotError {
        BotError::Serialization(err)
    }
}

fn format_approval_value(value: &str) -> String {
    let value: i8 = value.parse().unwrap_or(0);
    // TODO: when Spark will be allow to format text with different colors,
    // set green resp. red color here.
    if value > 0 {
        format!("+{}", value)
    } else {
        format!("{}", value)
    }
}

impl Bot {
    pub fn new() -> Bot {
        Bot { users: Vec::new() }
    }

    fn enable<'a>(&'a mut self, person_id: &str, email: &str, enabled: bool) -> &'a User {
        // FIXME: Replace linear search
        let pos = self.users.iter().position(
            |u| u.spark_person_id == person_id,
        );
        let user: &'a mut User = match pos {
            Some(pos) => &mut self.users[pos],
            None => {
                self.users.push(User::new(
                    String::from(person_id),
                    String::from(email),
                ));
                self.users.iter_mut().last().unwrap()
            }
        };
        user.enabled = enabled;
        user
    }

    fn get_approvals_msg(&self, event: gerrit::Event) -> Option<(&User, String)> {
        println!("[D] Incoming approvals: {:?}", event);

        let author = event.author;
        let change = event.change;
        let approvals = event.approvals;

        let approver = author.unwrap().username.clone();
        if approver == change.owner.username {
            // No need to notify about user's own approvals.
            return None;
        }

        if let Some(ref owner_email) = change.owner.email {
            // TODO: Fix linear search
            let users = &self.users;
            for user in users.iter() {
                if &user.email == owner_email {
                    if !user.enabled {
                        break;
                    }

                    if let Some(approvals) = approvals {
                        let msgs: Vec<String> = approvals
                            .iter()
                            .filter(|approval| {
                                let filtered = if let Some(ref old_value) = approval.old_value {
                                    old_value != &approval.value && approval.value != "0"
                                } else {
                                    approval.value != "0"
                                };
                                println!("Filtered approval: {:?}", !filtered);
                                filtered
                            })
                            .map(|approval| {
                                format!(
                                    "[{}]({}): {} ({}) from {}",
                                    change.subject,
                                    change.url,
                                    format_approval_value(&approval.value),
                                    approval.approval_type,
                                    approver
                                )
                            })
                            .collect();
                        return if !msgs.is_empty() {
                            Some((user, msgs.join("\n")))
                        } else {
                            None
                        };
                    }
                }
            }
        }
        None
    }

    pub fn save<P>(self, filename: P) -> Result<(), BotError>
    where
        P: AsRef<Path>,
    {
        let f = File::create(filename)?;
        serde_json::to_writer(f, &self)?;
        Ok(())
    }

    pub fn load<P>(filename: P) -> Result<Self, BotError>
    where
        P: AsRef<Path>,
    {
        let f = File::open(filename)?;
        let bot: Bot = serde_json::from_reader(f)?;
        Ok(bot)
    }

    pub fn num_users(&self) -> usize {
        self.users.len()
    }
}

#[derive(Debug)]
pub enum Action {
    Enable(spark::PersonId, spark::Email),
    Disable(spark::PersonId, spark::Email),
    UpdateApprovals(gerrit::Event),
    Help(spark::PersonId),
    Unknown(spark::PersonId),
    NoOp,
}

#[derive(Debug)]
pub struct Response {
    // TODO: Switch to a reference, since it should be alive inside of the Bot state
    pub person_id: spark::PersonId,
    pub message: String,
}

impl Response {
    pub fn new(person_id: spark::PersonId, message: String) -> Response {
        Response {
            person_id: person_id,
            message: message,
        }
    }
}

#[derive(Debug)]
pub enum Task {
    Reply(Response),
    ReplyAndSave(Response),
}

const GREETINGS_MSG: &'static str =
    r#"Hi. I am GerritBot (**in a very early alpha**). I can watch Gerrit reviews for you, and notify you about new +1/-1's.

To enable notifications, just type in 'enable'. A small note: your email in Spark and in Gerrit has to be the same. Otherwise, I can't match your accounts.

For more information, type in **help**.

By the way, my icon is made by
[ Madebyoliver ](http://www.flaticon.com/authors/madebyoliver)
from
[ www.flaticon.com ](http://www.flaticon.com)
and is licensed by
[ CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/).
"#;

const HELP_MSG: &'static str = r#"Commands:

`enable` I will start notifying you.

`disable` I will stop notifying you.

`help` This message
"#;

/// Action controller
/// Return new bot state and an optional message to send to the user
pub fn update(action: Action, bot: Bot) -> (Bot, Option<Task>) {
    let mut bot = bot;
    let task = match action {
        Action::Enable(person_id, email) => {
            bot.enable(&person_id, &email, true);
            let task = Task::ReplyAndSave(Response::new(
                person_id,
                String::from("Got it! Happy reviewing!"),
            ));
            Some(task)
        }
        Action::Disable(person_id, email) => {
            bot.enable(&person_id, &email, false);
            let task = Task::ReplyAndSave(Response::new(
                person_id,
                String::from("Got it! I will stay silent."),
            ));
            Some(task)
        }
        Action::UpdateApprovals(event) => {
            bot.get_approvals_msg(event).map(|(user, message)| {
                Task::Reply(Response::new(user.spark_person_id.clone(), message))
            })
        }
        Action::Help(person_id) => {
            Some(Task::Reply(
                Response::new(person_id, String::from(HELP_MSG)),
            ))
        }
        Action::Unknown(person_id) => {
            Some(Task::Reply(
                Response::new(person_id, String::from(GREETINGS_MSG)),
            ))
        }
        _ => None,
    };
    (bot, task)
}
<commit_msg>Fix grammar in comment.<commit_after>use std::path::Path;
use std::io;
use std::fs::File;
use std::convert;

use serde_json;

use gerrit;
use spark;

#[derive(Debug, Clone, Serialize, Deserialize)]
struct User {
    spark_person_id: spark::PersonId,
    email: spark::Email,
    enabled: bool,
}

impl User {
    fn new(person_id: spark::PersonId, email: spark::Email) -> User {
        User {
            spark_person_id: person_id,
            email: email,
            enabled: true,
        }
    }
}

/// Describes a state of the bot
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Bot {
    users: Vec<User>,
}

#[derive(Debug)]
pub enum BotError {
    Io(io::Error),
    Serialization(serde_json::Error),
}

impl convert::From<io::Error> for BotError {
    fn from(err: io::Error) -> BotError {
        BotError::Io(err)
    }
}

impl convert::From<serde_json::Error> for BotError {
    fn from(err: serde_json::Error) -> BotError {
        BotError::Serialization(err)
    }
}

fn format_approval_value(value: &str) -> String {
    let value: i8 = value.parse().unwrap_or(0);
    // TODO: when Spark will allow to format text with different colors, set
    // green resp. red color here.
    if value > 0 {
        format!("+{}", value)
    } else {
        format!("{}", value)
    }
}

impl Bot {
    pub fn new() -> Bot {
        Bot { users: Vec::new() }
    }

    fn enable<'a>(&'a mut self, person_id: &str, email: &str, enabled: bool) -> &'a User {
        // FIXME: Replace linear search
        let pos = self.users.iter().position(
            |u| u.spark_person_id == person_id,
        );
        let user: &'a mut User = match pos {
            Some(pos) => &mut self.users[pos],
            None => {
                self.users.push(User::new(
                    String::from(person_id),
                    String::from(email),
                ));
                self.users.iter_mut().last().unwrap()
            }
        };
        user.enabled = enabled;
        user
    }

    fn get_approvals_msg(&self, event: gerrit::Event) -> Option<(&User, String)> {
        println!("[D] Incoming approvals: {:?}", event);

        let author = event.author;
        let change = event.change;
        let approvals = event.approvals;

        let approver = author.unwrap().username.clone();
        if approver == change.owner.username {
            // No need to notify about user's own approvals.
            return None;
        }

        if let Some(ref owner_email) = change.owner.email {
            // TODO: Fix linear search
            let users = &self.users;
            for user in users.iter() {
                if &user.email == owner_email {
                    if !user.enabled {
                        break;
                    }

                    if let Some(approvals) = approvals {
                        let msgs: Vec<String> = approvals
                            .iter()
                            .filter(|approval| {
                                let filtered = if let Some(ref old_value) = approval.old_value {
                                    old_value != &approval.value && approval.value != "0"
                                } else {
                                    approval.value != "0"
                                };
                                println!("Filtered approval: {:?}", !filtered);
                                filtered
                            })
                            .map(|approval| {
                                format!(
                                    "[{}]({}): {} ({}) from {}",
                                    change.subject,
                                    change.url,
                                    format_approval_value(&approval.value),
                                    approval.approval_type,
                                    approver
                                )
                            })
                            .collect();
                        return if !msgs.is_empty() {
                            Some((user, msgs.join("\n")))
                        } else {
                            None
                        };
                    }
                }
            }
        }
        None
    }

    pub fn save<P>(self, filename: P) -> Result<(), BotError>
    where
        P: AsRef<Path>,
    {
        let f = File::create(filename)?;
        serde_json::to_writer(f, &self)?;
        Ok(())
    }

    pub fn load<P>(filename: P) -> Result<Self, BotError>
    where
        P: AsRef<Path>,
    {
        let f = File::open(filename)?;
        let bot: Bot = serde_json::from_reader(f)?;
        Ok(bot)
    }

    pub fn num_users(&self) -> usize {
        self.users.len()
    }
}

#[derive(Debug)]
pub enum Action {
    Enable(spark::PersonId, spark::Email),
    Disable(spark::PersonId, spark::Email),
    UpdateApprovals(gerrit::Event),
    Help(spark::PersonId),
    Unknown(spark::PersonId),
    NoOp,
}

#[derive(Debug)]
pub struct Response {
    // TODO: Switch to a reference, since it should be alive inside of the Bot state
    pub person_id: spark::PersonId,
    pub message: String,
}

impl Response {
    pub fn new(person_id: spark::PersonId, message: String) -> Response {
        Response {
            person_id: person_id,
            message: message,
        }
    }
}

#[derive(Debug)]
pub enum Task {
    Reply(Response),
    ReplyAndSave(Response),
}

const GREETINGS_MSG: &'static str =
    r#"Hi. I am GerritBot (**in a very early alpha**). I can watch Gerrit reviews for you, and notify you about new +1/-1's.

To enable notifications, just type in 'enable'. A small note: your email in Spark and in Gerrit has to be the same. Otherwise, I can't match your accounts.

For more information, type in **help**.

By the way, my icon is made by
[ Madebyoliver ](http://www.flaticon.com/authors/madebyoliver)
from
[ www.flaticon.com ](http://www.flaticon.com)
and is licensed by
[ CC 3.0 BY](http://creativecommons.org/licenses/by/3.0/).
"#;

const HELP_MSG: &'static str = r#"Commands:

`enable` I will start notifying you.

`disable` I will stop notifying you.

`help` This message
"#;

/// Action controller
/// Return new bot state and an optional message to send to the user
pub fn update(action: Action, bot: Bot) -> (Bot, Option<Task>) {
    let mut bot = bot;
    let task = match action {
        Action::Enable(person_id, email) => {
            bot.enable(&person_id, &email, true);
            let task = Task::ReplyAndSave(Response::new(
                person_id,
                String::from("Got it! Happy reviewing!"),
            ));
            Some(task)
        }
        Action::Disable(person_id, email) => {
            bot.enable(&person_id, &email, false);
            let task = Task::ReplyAndSave(Response::new(
                person_id,
                String::from("Got it! I will stay silent."),
            ));
            Some(task)
        }
        Action::UpdateApprovals(event) => {
            bot.get_approvals_msg(event).map(|(user, message)| {
                Task::Reply(Response::new(user.spark_person_id.clone(), message))
            })
        }
        Action::Help(person_id) => {
            Some(Task::Reply(
                Response::new(person_id, String::from(HELP_MSG)),
            ))
        }
        Action::Unknown(person_id) => {
            Some(Task::Reply(
                Response::new(person_id, String::from(GREETINGS_MSG)),
            ))
        }
        _ => None,
    };
    (bot, task)
}
<|endoftext|>


<commit_before>use std::io::{Result, Write};

use env::Env;
use file_saver::save_to_file;
use regex::Regex;

pub fn generate(env: &Env) {
    println!("generating sys build script for {}", env.config.library_name);

    let path = env.config.target_path.join("build.rs");

    println!("Generating file {:?}", path);
    save_to_file(&path, env.config.make_backup,
        |w| generate_build_script(w, env));
}

fn generate_build_script(w: &mut Write, env: &Env) -> Result<()> {
    try!(write!(w, "{}",
r##"extern crate pkg_config;

use pkg_config::{Config, Error};
use std::env;
use std::io::prelude::*;
use std::io;
use std::process;

fn main() {
    if let Err(s) = find() {
        let _ = writeln!(io::stderr(), "{}", s);
        process::exit(1);
    }
}

fn find() -> Result<(), Error> {
"##));

    let ns = env.namespaces.main();
    let regex = Regex::new(r"^lib(.+)\.so.*$").unwrap();
    let shared_libs: Vec<_> = ns.shared_libs.iter()
        .map(|s| regex.replace(s, "\"$1\""))
        .collect();

    try!(writeln!(w, "\tlet package_name = \"{}\";", ns.package_name.as_ref().unwrap()));
    try!(writeln!(w, "\tlet shared_libs = [{}];", shared_libs.join(", ")));
    try!(write!(w, "\tlet version = "));
    let versions = ns.versions.iter()
        .filter(|v| **v >= env.config.min_cfg_version)
        .skip(1)
        .collect::<Vec<_>>();
    for v in versions.iter().rev() {
        try!(write!(w, "if cfg!({}) {{\n\t\t\"{}\"\n\t}} else ", v.to_cfg(), v));
    }
    try!(writeln!(w, "{{\n\t\t\"{}\"\n\t}};", env.config.min_cfg_version));

    writeln!(w, "{}",
r##"
    if let Ok(lib_dir) = env::var("GTK_LIB_DIR") {
        for lib_ in shared_libs.iter() {
            println!("cargo:rustc-link-lib=dylib={}", lib_);
        }
        println!("cargo:rustc-link-search=native={}", lib_dir);
        return Ok(())
    }

    let target = env::var("TARGET").unwrap();
    let hardcode_shared_libs = target.contains("windows");

    let mut config = Config::new();
    config.atleast_version(version);
    if hardcode_shared_libs {
        config.cargo_metadata(false);
    }
    match config.probe(package_name) {
        Ok(library) => {
            if hardcode_shared_libs {
                for lib_ in shared_libs.iter() {
                    println!("cargo:rustc-link-lib=dylib={}", lib_);
                }
                for path in library.link_paths.iter() {
                    println!("cargo:rustc-link-search=native={}", path.to_str().unwrap());
                }
            }
            Ok(())
        }
        Err(Error::EnvNoPkgConfig(_)) | Err(Error::Command { .. }) => {
            for lib_ in shared_libs.iter() {
                println!("cargo:rustc-link-lib=dylib={}", lib_);
            }
            Ok(())
        }
        Err(err) => Err(err),
    }
}
"##)
}
<commit_msg>Replace some unwrap with expect calls<commit_after>use std::io::{Result, Write};

use env::Env;
use file_saver::save_to_file;
use regex::Regex;

pub fn generate(env: &Env) {
    println!("generating sys build script for {}", env.config.library_name);

    let path = env.config.target_path.join("build.rs");

    println!("Generating file {:?}", path);
    save_to_file(&path, env.config.make_backup,
        |w| generate_build_script(w, env));
}

fn generate_build_script(w: &mut Write, env: &Env) -> Result<()> {
    try!(write!(w, "{}",
r##"extern crate pkg_config;

use pkg_config::{Config, Error};
use std::env;
use std::io::prelude::*;
use std::io;
use std::process;

fn main() {
    if let Err(s) = find() {
        let _ = writeln!(io::stderr(), "{}", s);
        process::exit(1);
    }
}

fn find() -> Result<(), Error> {
"##));

    let ns = env.namespaces.main();
    let regex = Regex::new(r"^lib(.+)\.so.*$").expect("Regex failed");
    let shared_libs: Vec<_> = ns.shared_libs.iter()
        .map(|s| regex.replace(s, "\"$1\""))
        .collect();

    try!(writeln!(w, "\tlet package_name = \"{}\";",
                  ns.package_name.as_ref().expect("Package name doesn't exist")));
    try!(writeln!(w, "\tlet shared_libs = [{}];", shared_libs.join(", ")));
    try!(write!(w, "\tlet version = "));
    let versions = ns.versions.iter()
        .filter(|v| **v >= env.config.min_cfg_version)
        .skip(1)
        .collect::<Vec<_>>();
    for v in versions.iter().rev() {
        try!(write!(w, "if cfg!({}) {{\n\t\t\"{}\"\n\t}} else ", v.to_cfg(), v));
    }
    try!(writeln!(w, "{{\n\t\t\"{}\"\n\t}};", env.config.min_cfg_version));

    writeln!(w, "{}",
r##"
    if let Ok(lib_dir) = env::var("GTK_LIB_DIR") {
        for lib_ in shared_libs.iter() {
            println!("cargo:rustc-link-lib=dylib={}", lib_);
        }
        println!("cargo:rustc-link-search=native={}", lib_dir);
        return Ok(())
    }

    let target = env::var("TARGET").expect("TARGET environment variable doesn't exist");
    let hardcode_shared_libs = target.contains("windows");

    let mut config = Config::new();
    config.atleast_version(version);
    if hardcode_shared_libs {
        config.cargo_metadata(false);
    }
    match config.probe(package_name) {
        Ok(library) => {
            if hardcode_shared_libs {
                for lib_ in shared_libs.iter() {
                    println!("cargo:rustc-link-lib=dylib={}", lib_);
                }
                for path in library.link_paths.iter() {
                    println!("cargo:rustc-link-search=native={}",
                             path.to_str().expect("library path doesn't exist"));
                }
            }
            Ok(())
        }
        Err(Error::EnvNoPkgConfig(_)) | Err(Error::Command { .. }) => {
            for lib_ in shared_libs.iter() {
                println!("cargo:rustc-link-lib=dylib={}", lib_);
            }
            Ok(())
        }
        Err(err) => Err(err),
    }
}
"##)
}
<|endoftext|>


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

use crate::colour::Colour;
use crate::grid::Grid;

// Represent the state of the game as a graph.  One node for each cell.  There is an edge between
// two cells if and only if they are the same colour and have a distance of 1 according to the
// Manhattan metric.
//
// The game has only one real operation (i.e. not counting level generation): Switching the colour
// of the connected component containing the top left cell to whichever colour the clicked cell
// has.  This results in said component growing by every component it neighbours which has its new
// colour.  In essence, the aim of the gaim is to join connected components until only one is
// left.  Fewer clicks is better.
//
// So, we represent the game state as a collection of connected components, each of which has a
// colour, a list of coordinates of the constituent cells, and a list of it s neighbours.  As we
// do all our operations on connected components, we actually work not with the graph of
// neighbouring cells but with a graph of connected components.  The graph of connected components
// is made up of one node representing each connected component and an edge between any two
// connected components that have cells which share an edge, i.e. two cells which would have been
// connected by an edge in the original graph if they had had the same colour (which they did
// not).

struct Position {
    row: usize,
    column: usize,
}

struct ConnectedComponent {
    colour: Colour,
    cells: HashSet<Position>,
}

struct Graph {
    neighours: HashMap<ConnectedComponent, Vec<ConnectedComponent>>,
}
<commit_msg>Derive traits for Position<commit_after>use std::collections::HashMap;

use crate::colour::Colour;
use crate::grid::Grid;

// Represent the state of the game as a graph.  One node for each cell.  There is an edge between
// two cells if and only if they are the same colour and have a distance of 1 according to the
// Manhattan metric.
//
// The game has only one real operation (i.e. not counting level generation): Switching the colour
// of the connected component containing the top left cell to whichever colour the clicked cell
// has.  This results in said component growing by every component it neighbours which has its new
// colour.  In essence, the aim of the gaim is to join connected components until only one is
// left.  Fewer clicks is better.
//
// So, we represent the game state as a collection of connected components, each of which has a
// colour, a list of coordinates of the constituent cells, and a list of it s neighbours.  As we
// do all our operations on connected components, we actually work not with the graph of
// neighbouring cells but with a graph of connected components.  The graph of connected components
// is made up of one node representing each connected component and an edge between any two
// connected components that have cells which share an edge, i.e. two cells which would have been
// connected by an edge in the original graph if they had had the same colour (which they did
// not).

#[derive(Eq, PartialEq, Hash)]
struct Position {
    row: usize,
    column: usize,
}

struct ConnectedComponent {
    colour: Colour,
    cells: HashSet<Position>,
}

struct Graph {
    neighours: HashMap<ConnectedComponent, Vec<ConnectedComponent>>,
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use toml::Value;

use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagstore::storeid::IntoStoreId;
use libimagstore::storeid::StoreIdIterator;
use libimagentrylink::internal::InternalLinker;

use toml_query::read::TomlValueReadExt;
use toml_query::insert::TomlValueInsertExt;

use error::Result;
use error::AnnotationErrorKind as AEK;
use error::AnnotationError as AE;
use error::ResultExt;

use iter::*;

pub trait Annotateable {
    fn annotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<FileLockEntry<'a>>;
    fn denotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<Option<FileLockEntry<'a>>>;
    fn annotations<'a>(&self, store: &'a Store) -> Result<AnnotationIter<'a>>;
    fn is_annotation(&self) -> Result<bool>;
}

impl Annotateable for Entry {

    /// Annotate an entry, returns the new entry which is used to annotate
    fn annotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<FileLockEntry<'a>> {
        use module_path::ModuleEntryPath;
        store.retrieve(try!(ModuleEntryPath::new(ann_name).into_storeid()))
            .map_err(From::from)
            .and_then(|mut anno| {
                {
                    let header = anno.get_header_mut();
                    try!(header.insert("annotation.is_annotation", Value::Boolean(true)));
                    try!(header.insert("annotation.name", Value::String(String::from(ann_name))));
                }
                Ok(anno)
            })
            .and_then(|mut anno| {
                anno.add_internal_link(self)
                    .chain_err(|| AEK::LinkingError)
                    .map(|_| anno)
            })
    }

    /// Checks the current entry for all annotations and removes the one where the name is
    /// `ann_name`, which is then returned
    fn denotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<Option<FileLockEntry<'a>>> {
        for annotation in self.annotations(store)? {
            let mut anno = try!(annotation);
            let name = match anno.get_header().read("annotation.name")? {
                None      => continue,
                Some(val) => match *val {
                    Value::String(ref name) => name.clone(),
                    _ => return Err(AE::from_kind(AEK::HeaderTypeError)),
                },
            };

            if name == ann_name {
                let _ = try!(self.remove_internal_link(&mut anno));
            }
        }

        Ok(None)
    }

    /// Get all annotations of an entry
    fn annotations<'a>(&self, store: &'a Store) -> Result<AnnotationIter<'a>> {
        self.get_internal_links()
            .map_err(From::from)
            .map(|iter| StoreIdIterator::new(Box::new(iter.map(|e| e.get_store_id().clone()))))
            .map(|i| AnnotationIter::new(i, store))
    }

    fn is_annotation(&self) -> Result<bool> {
        self.get_header()
            .read("annotation.is_annotation")
            .map_err(From::from)
            .and_then(|res| match res {
                Some(&Value::Boolean(b)) => Ok(b),
                None                     => Ok(false),
                _                        => Err(AE::from_kind(AEK::HeaderTypeError)),
            })
    }

}

<commit_msg>Fix: Return annotation object when found<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use toml::Value;

use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Store;
use libimagstore::storeid::IntoStoreId;
use libimagstore::storeid::StoreIdIterator;
use libimagentrylink::internal::InternalLinker;

use toml_query::read::TomlValueReadExt;
use toml_query::insert::TomlValueInsertExt;

use error::Result;
use error::AnnotationErrorKind as AEK;
use error::AnnotationError as AE;
use error::ResultExt;

use iter::*;

pub trait Annotateable {
    fn annotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<FileLockEntry<'a>>;
    fn denotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<Option<FileLockEntry<'a>>>;
    fn annotations<'a>(&self, store: &'a Store) -> Result<AnnotationIter<'a>>;
    fn is_annotation(&self) -> Result<bool>;
}

impl Annotateable for Entry {

    /// Annotate an entry, returns the new entry which is used to annotate
    fn annotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<FileLockEntry<'a>> {
        use module_path::ModuleEntryPath;
        store.retrieve(try!(ModuleEntryPath::new(ann_name).into_storeid()))
            .map_err(From::from)
            .and_then(|mut anno| {
                {
                    let header = anno.get_header_mut();
                    try!(header.insert("annotation.is_annotation", Value::Boolean(true)));
                    try!(header.insert("annotation.name", Value::String(String::from(ann_name))));
                }
                Ok(anno)
            })
            .and_then(|mut anno| {
                anno.add_internal_link(self)
                    .chain_err(|| AEK::LinkingError)
                    .map(|_| anno)
            })
    }

    /// Checks the current entry for all annotations and removes the one where the name is
    /// `ann_name`, which is then returned
    fn denotate<'a>(&mut self, store: &'a Store, ann_name: &str) -> Result<Option<FileLockEntry<'a>>> {
        for annotation in self.annotations(store)? {
            let mut anno = try!(annotation);
            let name = match anno.get_header().read("annotation.name")? {
                None      => continue,
                Some(val) => match *val {
                    Value::String(ref name) => name.clone(),
                    _ => return Err(AE::from_kind(AEK::HeaderTypeError)),
                },
            };

            if name == ann_name {
                let _ = try!(self.remove_internal_link(&mut anno));
                return Ok(Some(anno));
            }
        }

        Ok(None)
    }

    /// Get all annotations of an entry
    fn annotations<'a>(&self, store: &'a Store) -> Result<AnnotationIter<'a>> {
        self.get_internal_links()
            .map_err(From::from)
            .map(|iter| StoreIdIterator::new(Box::new(iter.map(|e| e.get_store_id().clone()))))
            .map(|i| AnnotationIter::new(i, store))
    }

    fn is_annotation(&self) -> Result<bool> {
        self.get_header()
            .read("annotation.is_annotation")
            .map_err(From::from)
            .and_then(|res| match res {
                Some(&Value::Boolean(b)) => Ok(b),
                None                     => Ok(false),
                _                        => Err(AE::from_kind(AEK::HeaderTypeError)),
            })
    }

}

<|endoftext|>


<commit_before>use crate::rt::compute_raw_varint32_size;
use crate::rt::tag_size;
use crate::rt::ProtobufFixed;
use crate::rt::ProtobufVarint;
use crate::zigzag::ProtobufVarintZigzag;
use crate::Enum;
use crate::EnumOrUnknown;

/// Size of serialized repeated packed field, excluding length and tag.
pub(crate) fn vec_packed_varint_data_size<T: ProtobufVarint>(vec: &[T]) -> u64 {
    vec.iter()
        .map(|v| v.len_varint() as u64)
        .fold(0, |a, i| a + i)
}

/// Size of serialized repeated packed field, excluding length and tag.
pub(crate) fn vec_packed_varint_zigzag_data_size<T: ProtobufVarintZigzag>(vec: &[T]) -> u64 {
    vec.iter()
        .map(|v| v.len_varint_zigzag())
        .fold(0, |a, i| a + i)
}

/// Size of serialized repeated packed enum field, excluding length and tag.
pub(crate) fn vec_packed_enum_or_unknown_data_size<E: Enum>(vec: &[EnumOrUnknown<E>]) -> u64 {
    vec.iter()
        .map(|e| compute_raw_varint32_size(e.value() as u32))
        .fold(0, |a, i| a + i)
}

/// Size of serialized data with length prefix and tag
#[inline]
pub fn vec_packed_varint_size<T: ProtobufVarint>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
#[inline]
fn vec_packed_varint_zigzag_size<T: ProtobufVarintZigzag>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_zigzag_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag.
#[inline]
pub fn vec_packed_sint32_size(field_number: u32, vec: &[i32]) -> u64 {
    vec_packed_varint_zigzag_size(field_number, vec)
}

/// Size of serialized data with length prefix and tag.
#[inline]
pub fn vec_packed_sint64_size(field_number: u32, vec: &[i64]) -> u64 {
    vec_packed_varint_zigzag_size(field_number, vec)
}

/// Size of serialized data with length prefix and tag
#[inline]
pub fn vec_packed_enum_or_unknown_size<E: Enum>(
    field_number: u32,
    vec: &[EnumOrUnknown<E>],
) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_enum_or_unknown_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute data size of fixed encoding of repeated field data.
pub(crate) fn vec_packed_fixed_data_size<V: ProtobufFixed>(vec: &[V]) -> u64 {
    (vec.len() as u64) * (V::LEN as u64)
}

/// Compute field size (data plus header) of fixed encoding of repeated field.
#[inline]
pub fn vec_packed_fixed_size<V: ProtobufFixed>(field_number: u32, vec: &[V]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_fixed_data_size::<V>(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}
<commit_msg>Modernize codebase<commit_after>use crate::rt::compute_raw_varint32_size;
use crate::rt::tag_size;
use crate::rt::ProtobufFixed;
use crate::rt::ProtobufVarint;
use crate::zigzag::ProtobufVarintZigzag;
use crate::Enum;
use crate::EnumOrUnknown;

/// Size of serialized repeated packed field, excluding length and tag.
pub(crate) fn vec_packed_varint_data_size<T: ProtobufVarint>(vec: &[T]) -> u64 {
    vec.iter().map(|v| v.len_varint() as u64).sum()
}

/// Size of serialized repeated packed field, excluding length and tag.
pub(crate) fn vec_packed_varint_zigzag_data_size<T: ProtobufVarintZigzag>(vec: &[T]) -> u64 {
    vec.iter().map(|v| v.len_varint_zigzag()).sum()
}

/// Size of serialized repeated packed enum field, excluding length and tag.
pub(crate) fn vec_packed_enum_or_unknown_data_size<E: Enum>(vec: &[EnumOrUnknown<E>]) -> u64 {
    vec.iter()
        .map(|e| compute_raw_varint32_size(e.value() as u32))
        .sum()
}

/// Size of serialized data with length prefix and tag
#[inline]
pub fn vec_packed_varint_size<T: ProtobufVarint>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag
#[inline]
fn vec_packed_varint_zigzag_size<T: ProtobufVarintZigzag>(field_number: u32, vec: &[T]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_varint_zigzag_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Size of serialized data with length prefix and tag.
#[inline]
pub fn vec_packed_sint32_size(field_number: u32, vec: &[i32]) -> u64 {
    vec_packed_varint_zigzag_size(field_number, vec)
}

/// Size of serialized data with length prefix and tag.
#[inline]
pub fn vec_packed_sint64_size(field_number: u32, vec: &[i64]) -> u64 {
    vec_packed_varint_zigzag_size(field_number, vec)
}

/// Size of serialized data with length prefix and tag
#[inline]
pub fn vec_packed_enum_or_unknown_size<E: Enum>(
    field_number: u32,
    vec: &[EnumOrUnknown<E>],
) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_enum_or_unknown_data_size(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}

/// Compute data size of fixed encoding of repeated field data.
pub(crate) fn vec_packed_fixed_data_size<V: ProtobufFixed>(vec: &[V]) -> u64 {
    (vec.len() as u64) * (V::LEN as u64)
}

/// Compute field size (data plus header) of fixed encoding of repeated field.
#[inline]
pub fn vec_packed_fixed_size<V: ProtobufFixed>(field_number: u32, vec: &[V]) -> u64 {
    if vec.is_empty() {
        0
    } else {
        let data_size = vec_packed_fixed_data_size::<V>(vec);
        tag_size(field_number) + data_size.len_varint() + data_size
    }
}
<|endoftext|>


<commit_before>#[test]
fn card_cmp_less() {
    let lesser = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Hearts
    };
    let greater = ::card::Card {
        value: ::card::Value::Six,
        suit: ::card::Suit::Spades
    };

    assert_eq!(lesser.partial_cmp(&greater).unwrap(), cmp::Ordering::Less);
}

#[test]
fn card_cmp_greater() {
    let lesser = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Hearts
    };
    let greater = ::card::Card {
        value: ::card::Value::Six,
        suit: ::card::Suit::Spades
    };

    assert_eq!(greater.partial_cmp(&lesser).unwrap(), cmp::Ordering::Greater);
}

#[test]
fn card_cmp_equal() {
    let heart_card = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Hearts
    };
    let spade_card = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Spades
    };

    assert_eq!(heart_card.partial_cmp(&spade_card).unwrap(), cmp::Ordering::Equal);
}
<commit_msg>Imported std::cmp<commit_after>use std::cmp;

#[test]
fn card_cmp_less() {
    let lesser = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Hearts
    };
    let greater = ::card::Card {
        value: ::card::Value::Six,
        suit: ::card::Suit::Spades
    };

    assert_eq!(lesser.partial_cmp(&greater).unwrap(), cmp::Ordering::Less);
}

#[test]
fn card_cmp_greater() {
    let lesser = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Hearts
    };
    let greater = ::card::Card {
        value: ::card::Value::Six,
        suit: ::card::Suit::Spades
    };

    assert_eq!(greater.partial_cmp(&lesser).unwrap(), cmp::Ordering::Greater);
}

#[test]
fn card_cmp_equal() {
    let heart_card = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Hearts
    };
    let spade_card = ::card::Card {
        value: ::card::Value::Five,
        suit: ::card::Suit::Spades
    };

    assert_eq!(heart_card.partial_cmp(&spade_card).unwrap(), cmp::Ordering::Equal);
}
<|endoftext|>


<commit_before>use std::process::Command;
use std::path::Path;

use clap::{App, Arg};

#[derive(Debug)]
pub struct Args {
    pub cmd: String,
    pub paths: Vec<String>,
    pub filters: Vec<String>,
    pub ignores: Vec<String>,
    pub clear_screen: bool,
    pub restart: bool,
    pub debug: bool,
    pub run_initially: bool,
    pub no_vcs_ignore: bool,
    pub poll: bool,
    pub poll_interval: u32,
}

#[cfg(target_family = "windows")]
pub fn clear_screen() {
    let _ = Command::new("cls").status();
}

#[cfg(target_family = "unix")]
pub fn clear_screen() {
    let _ = Command::new("clear").status();
}

pub fn get_args() -> Args {
    let args = App::new("watchexec")
        .version(crate_version!())
        .about("Execute commands when watched files change")
        .arg(Arg::with_name("path")
            .help("Path to watch [default: .]")
            .short("w")
            .long("watch")
            .number_of_values(1)
            .multiple(true)
            .takes_value(true))
        .arg(Arg::with_name("command")
            .help("Command to execute")
            .multiple(true)
            .required(true))
        .arg(Arg::with_name("extensions")
            .help("Comma-separated list of file extensions to watch (js,css,html)")
            .short("e")
            .long("exts")
            .takes_value(true))
        .arg(Arg::with_name("clear")
            .help("Clear screen before executing command")
            .short("c")
            .long("clear"))
        .arg(Arg::with_name("restart")
            .help("Restart the process if it's still running")
            .short("r")
            .long("restart"))
        .arg(Arg::with_name("debug")
            .help("Print debugging messages to stderr")
            .short("d")
            .long("debug"))
        .arg(Arg::with_name("filter")
            .help("Ignore all modifications except those matching the pattern")
            .short("f")
            .long("filter")
            .number_of_values(1)
            .multiple(true)
            .takes_value(true)
            .value_name("pattern"))
        .arg(Arg::with_name("ignore")
            .help("Ignore modifications to paths matching the pattern")
            .short("i")
            .long("ignore")
            .number_of_values(1)
            .multiple(true)
            .takes_value(true)
            .value_name("pattern"))
        .arg(Arg::with_name("no-vcs-ignore")
            .help("Skip auto-loading of .gitignore files for filtering")
            .long("no-vcs-ignore"))
        .arg(Arg::with_name("run-initially")
            .help("Run command initially, before first file change")
            .long("run-initially"))
        .arg(Arg::with_name("poll")
            .help("Forces polling mode")
            .long("force-poll")
            .value_name("interval"))
        .get_matches();

    let cmd = values_t!(args.values_of("command"), String).unwrap().join(" ");
    let paths = values_t!(args.values_of("path"), String).unwrap_or(vec![String::from(".")]);
    let mut filters = values_t!(args.values_of("filter"), String).unwrap_or(vec![]);

    if let Some(extensions) = args.values_of("extensions") {
        for exts in extensions {
            filters.extend(exts.split(',')
                .filter(|ext| !ext.is_empty())
                .map(|ext| format!("*.{}", ext.replace(".", ""))));

        }
    }

    let dotted_dirs = Path::new(".*").join("*");
    let default_ignores = vec!["*/.DS_Store", "*.pyc", "*.swp", dotted_dirs.to_str().unwrap()];
    let mut ignores = vec![];

    for default_ignore in default_ignores {
        ignores.push(String::from(default_ignore));
    }

    ignores.extend(values_t!(args.values_of("ignore"), String).unwrap_or(vec![]));
    let poll_interval = if args.occurrences_of("poll") > 0 {
        value_t!(args.value_of("poll"), u32).unwrap_or_else(|e| e.exit())
    } else {
        1000
    };

    Args {
        cmd: cmd,
        paths: paths,
        filters: filters,
        ignores: ignores,
        clear_screen: args.is_present("clear"),
        restart: args.is_present("restart"),
        debug: args.is_present("debug"),
        run_initially: args.is_present("run-initially"),
        no_vcs_ignore: args.is_present("no-vcs-ignore"),
        poll: args.occurrences_of("poll") > 0,
        poll_interval: poll_interval,
    }
}
<commit_msg>Fix dotted dir default filter to only fire on dirs<commit_after>use std::path::MAIN_SEPARATOR;
use std::process::Command;

use clap::{App, Arg};

#[derive(Debug)]
pub struct Args {
    pub cmd: String,
    pub paths: Vec<String>,
    pub filters: Vec<String>,
    pub ignores: Vec<String>,
    pub clear_screen: bool,
    pub restart: bool,
    pub debug: bool,
    pub run_initially: bool,
    pub no_vcs_ignore: bool,
    pub poll: bool,
    pub poll_interval: u32,
}

#[cfg(target_family = "windows")]
pub fn clear_screen() {
    let _ = Command::new("cls").status();
}

#[cfg(target_family = "unix")]
pub fn clear_screen() {
    let _ = Command::new("clear").status();
}

pub fn get_args() -> Args {
    let args = App::new("watchexec")
        .version(crate_version!())
        .about("Execute commands when watched files change")
        .arg(Arg::with_name("path")
            .help("Path to watch [default: .]")
            .short("w")
            .long("watch")
            .number_of_values(1)
            .multiple(true)
            .takes_value(true))
        .arg(Arg::with_name("command")
            .help("Command to execute")
            .multiple(true)
            .required(true))
        .arg(Arg::with_name("extensions")
            .help("Comma-separated list of file extensions to watch (js,css,html)")
            .short("e")
            .long("exts")
            .takes_value(true))
        .arg(Arg::with_name("clear")
            .help("Clear screen before executing command")
            .short("c")
            .long("clear"))
        .arg(Arg::with_name("restart")
            .help("Restart the process if it's still running")
            .short("r")
            .long("restart"))
        .arg(Arg::with_name("debug")
            .help("Print debugging messages to stderr")
            .short("d")
            .long("debug"))
        .arg(Arg::with_name("filter")
            .help("Ignore all modifications except those matching the pattern")
            .short("f")
            .long("filter")
            .number_of_values(1)
            .multiple(true)
            .takes_value(true)
            .value_name("pattern"))
        .arg(Arg::with_name("ignore")
            .help("Ignore modifications to paths matching the pattern")
            .short("i")
            .long("ignore")
            .number_of_values(1)
            .multiple(true)
            .takes_value(true)
            .value_name("pattern"))
        .arg(Arg::with_name("no-vcs-ignore")
            .help("Skip auto-loading of .gitignore files for filtering")
            .long("no-vcs-ignore"))
        .arg(Arg::with_name("run-initially")
            .help("Run command initially, before first file change")
            .long("run-initially"))
        .arg(Arg::with_name("poll")
            .help("Forces polling mode")
            .long("force-poll")
            .value_name("interval"))
        .get_matches();

    let cmd = values_t!(args.values_of("command"), String).unwrap().join(" ");
    let paths = values_t!(args.values_of("path"), String).unwrap_or(vec![String::from(".")]);
    let mut filters = values_t!(args.values_of("filter"), String).unwrap_or(vec![]);

    if let Some(extensions) = args.values_of("extensions") {
        for exts in extensions {
            filters.extend(exts.split(',')
                .filter(|ext| !ext.is_empty())
                .map(|ext| format!("*.{}", ext.replace(".", ""))));

        }
    }

    let mut ignores = vec![];
    let default_ignores = vec![
        format!("*{}.*{}*", MAIN_SEPARATOR, MAIN_SEPARATOR),
        format!("*{}.DS_Store", MAIN_SEPARATOR),
        String::from("*.pyc"),
        String::from("*.swp")];

    ignores.extend(default_ignores);
    ignores.extend(values_t!(args.values_of("ignore"), String).unwrap_or(vec![]));

    let poll_interval = if args.occurrences_of("poll") > 0 {
        value_t!(args.value_of("poll"), u32).unwrap_or_else(|e| e.exit())
    } else {
        1000
    };

    Args {
        cmd: cmd,
        paths: paths,
        filters: filters,
        ignores: ignores,
        clear_screen: args.is_present("clear"),
        restart: args.is_present("restart"),
        debug: args.is_present("debug"),
        run_initially: args.is_present("run-initially"),
        no_vcs_ignore: args.is_present("no-vcs-ignore"),
        poll: args.occurrences_of("poll") > 0,
        poll_interval: poll_interval,
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix error which lead to counting to many components<commit_after><|endoftext|>


<commit_before>use module::*;
use scoped_map::ScopedMap;

#[deriving(Eq, TotalEq, Hash, Clone, Show)]
pub struct Name {
    pub name: ~str,
    pub uid: uint
}

impl Str for Name {
    fn as_slice<'a>(&'a self) -> &'a str {
        self.name.as_slice()
    }
    fn into_owned(self) -> ~str {
        self.name
    }
}

struct Renamer {
    uniques: ScopedMap<~str, Name>,
    unique_id: uint
}

impl Renamer {

    fn rename_bindings(&mut self, bindings: ~[Binding<~str>]) -> ~[Binding<Name>] {
        //Add all bindings in the scope
        for bind in bindings.iter() {
            self.make_unique(bind.name.clone());
        }
        bindings.move_iter().map(|binding| {
            let Binding { name: name, expression: expression, typeDecl: typeDecl, arity: arity  } = binding;
            let n = self.uniques.find(&name).map(|u| u.clone())
                .expect(format!("Error: lambda_lift: Undefined variable {}", name));
            Binding {
                name: n,
                expression: self.rename(expression),
                typeDecl: typeDecl,
                arity: arity
            }
        }).collect()
    }

    fn rename(&mut self, input_expr: TypedExpr<~str>) -> TypedExpr<Name> {
        let TypedExpr { expr: expr, typ: typ, location: location } = input_expr;
        let e = match expr {
            Number(n) => Number(n),
            Rational(r) => Rational(r),
            String(s) => String(s),
            Char(c) => Char(c),
            Identifier(i) => Identifier(self.get_name(i)),
            Apply(func, arg) => Apply(~self.rename(*func), ~self.rename(*arg)),
            Lambda(arg, body) => {
                self.uniques.enter_scope();
                let l = Lambda(self.make_unique(arg), ~self.rename(*body));
                self.uniques.exit_scope();
                l
            }
            Let(bindings, expr) => {
                self.uniques.enter_scope();
                let bs = self.rename_bindings(bindings);
                let l = Let(bs, ~self.rename(*expr));
                self.uniques.exit_scope();
                l
            }
            Case(expr, alts) => {
                let a = alts.move_iter().map(
                    |Alternative { pattern: Located { location: loc, node: pattern }, expression: expression }| {
                    self.uniques.enter_scope();
                    let a = Alternative {
                        pattern: Located { location: loc, node: self.rename_pattern(pattern) },
                        expression: self.rename(expression)
                    };
                    self.uniques.exit_scope();
                    a
                }).collect();
                Case(~self.rename(*expr), a)
            }
        };
        let mut t = TypedExpr::with_location(e, location);
        t.typ = typ;
        t
    }

    fn rename_pattern(&mut self, pattern: Pattern<~str>) -> Pattern<Name> {
        match pattern {
            NumberPattern(i) => NumberPattern(i),
            ConstructorPattern(s, ps) => {
                let ps2 = ps.move_iter().map(|p| self.rename_pattern(p)).collect();
                ConstructorPattern(Name { name: s, uid: 0}, ps2)
            }
            IdentifierPattern(s) => IdentifierPattern(self.make_unique(s))
        }
    }
    fn get_name(&self, s: ~str) -> Name {
        match self.uniques.find(&s) {
            Some(&Name { uid: uid, .. }) => Name { name: s, uid: uid },
            None => Name { name: s, uid: 0 }//If the variable is not found in variables it is a global variable
        }
    }

    fn rename_binding(&mut self, binding: Binding<~str>) -> Binding<Name> {
        let Binding { name: name, expression: expression, typeDecl: td, arity: a } = binding;
        Binding {
            name: Name { name: name, uid: 0 },
            expression: self.rename(expression),
            typeDecl: td,
            arity: a
        }
    }

    fn make_unique(&mut self, name: ~str) -> Name {
        self.unique_id += 1;
        let u = Name { name: name.clone(), uid: self.unique_id};
        self.uniques.insert(name, u.clone());
        u
    }
}
pub fn rename_expr(expr: TypedExpr<~str>) -> TypedExpr<Name> {
    let mut renamer = Renamer { uniques: ScopedMap::new(), unique_id: 1 };
    renamer.rename(expr)
}

pub fn rename_module(module: Module<~str>) -> Module<Name> {
    let mut renamer = Renamer { uniques: ScopedMap::new(), unique_id: 1 };
    let Module {
        name: name,
        classes : classes,
        dataDefinitions: data_definitions,
        typeDeclarations: typeDeclarations,
        bindings : bindings,
        instances: instances
    } = module;

    let data_definitions2 = data_definitions.move_iter().map(|data| {
        let DataDefinition {
            constructors : ctors,
            typ : typ,
            parameters : parameters
        } = data;
        DataDefinition {
            typ : typ,
            parameters : parameters,
            constructors : ctors.move_iter().map(|ctor| {
                let Constructor {
                    name : name,
                    typ : typ,
                    tag : tag,
                    arity : arity
                } = ctor;
                Constructor {
                    name : Name { name: name, uid: 0 },
                    typ : typ,
                    tag : tag,
                    arity : arity
                }
            }).collect()
        }
    }).collect();

    let instances2 = instances.move_iter().map(|instance| {
        let Instance {
            bindings : bindings,
            constraints : constraints,
            typ : typ,
            classname : classname
        } = instance;
        Instance {
            bindings : bindings.move_iter().map(|b| renamer.rename_binding(b)).collect(),
            constraints : constraints,
            typ : typ,
            classname : classname
        }
    }).collect();

    let bindings2 : ~[Binding<Name>] = bindings.move_iter().map(|b| renamer.rename_binding(b)).collect();

    Module {
        name: renamer.make_unique(name),
        classes : classes,
        dataDefinitions: data_definitions2,
        typeDeclarations: typeDeclarations,
        bindings : bindings2,
        instances: instances2
    }
}

<commit_msg>Added Do expressions to the renamer<commit_after>use module::*;
use scoped_map::ScopedMap;

#[deriving(Eq, TotalEq, Hash, Clone, Show)]
pub struct Name {
    pub name: ~str,
    pub uid: uint
}

impl Str for Name {
    fn as_slice<'a>(&'a self) -> &'a str {
        self.name.as_slice()
    }
    fn into_owned(self) -> ~str {
        self.name
    }
}

struct Renamer {
    uniques: ScopedMap<~str, Name>,
    unique_id: uint
}

impl Renamer {

    fn rename_bindings(&mut self, bindings: ~[Binding<~str>]) -> ~[Binding<Name>] {
        //Add all bindings in the scope
        for bind in bindings.iter() {
            self.make_unique(bind.name.clone());
        }
        bindings.move_iter().map(|binding| {
            let Binding { name: name, expression: expression, typeDecl: typeDecl, arity: arity  } = binding;
            let n = self.uniques.find(&name).map(|u| u.clone())
                .expect(format!("Error: lambda_lift: Undefined variable {}", name));
            Binding {
                name: n,
                expression: self.rename(expression),
                typeDecl: typeDecl,
                arity: arity
            }
        }).collect()
    }

    fn rename(&mut self, input_expr: TypedExpr<~str>) -> TypedExpr<Name> {
        let TypedExpr { expr: expr, typ: typ, location: location } = input_expr;
        let e = match expr {
            Number(n) => Number(n),
            Rational(r) => Rational(r),
            String(s) => String(s),
            Char(c) => Char(c),
            Identifier(i) => Identifier(self.get_name(i)),
            Apply(func, arg) => Apply(~self.rename(*func), ~self.rename(*arg)),
            Lambda(arg, body) => {
                self.uniques.enter_scope();
                let l = Lambda(self.make_unique(arg), ~self.rename(*body));
                self.uniques.exit_scope();
                l
            }
            Let(bindings, expr) => {
                self.uniques.enter_scope();
                let bs = self.rename_bindings(bindings);
                let l = Let(bs, ~self.rename(*expr));
                self.uniques.exit_scope();
                l
            }
            Case(expr, alts) => {
                let a = alts.move_iter().map(
                    |Alternative { pattern: Located { location: loc, node: pattern }, expression: expression }| {
                    self.uniques.enter_scope();
                    let a = Alternative {
                        pattern: Located { location: loc, node: self.rename_pattern(pattern) },
                        expression: self.rename(expression)
                    };
                    self.uniques.exit_scope();
                    a
                }).collect();
                Case(~self.rename(*expr), a)
            }
            Do(bindings, expr) => {
                let bs = bindings.move_iter().map(|bind| {
                    match bind {
                        DoExpr(expr) => DoExpr(self.rename(expr)),
                        DoLet(bs) => DoLet(self.rename_bindings(bs)),
                        DoBind(pattern, expr) => {
                            let Located { location: location, node: node } = pattern;
                            let loc = Located { location: location, node: self.rename_pattern(node) };
                            DoBind(loc, self.rename(expr))
                        }
                    }
                }).collect();
                Do(bs, ~self.rename(*expr))
            }
        };
        let mut t = TypedExpr::with_location(e, location);
        t.typ = typ;
        t
    }

    fn rename_pattern(&mut self, pattern: Pattern<~str>) -> Pattern<Name> {
        match pattern {
            NumberPattern(i) => NumberPattern(i),
            ConstructorPattern(s, ps) => {
                let ps2 = ps.move_iter().map(|p| self.rename_pattern(p)).collect();
                ConstructorPattern(Name { name: s, uid: 0}, ps2)
            }
            IdentifierPattern(s) => IdentifierPattern(self.make_unique(s))
        }
    }
    fn get_name(&self, s: ~str) -> Name {
        match self.uniques.find(&s) {
            Some(&Name { uid: uid, .. }) => Name { name: s, uid: uid },
            None => Name { name: s, uid: 0 }//If the variable is not found in variables it is a global variable
        }
    }

    fn rename_binding(&mut self, binding: Binding<~str>) -> Binding<Name> {
        let Binding { name: name, expression: expression, typeDecl: td, arity: a } = binding;
        Binding {
            name: Name { name: name, uid: 0 },
            expression: self.rename(expression),
            typeDecl: td,
            arity: a
        }
    }

    fn make_unique(&mut self, name: ~str) -> Name {
        self.unique_id += 1;
        let u = Name { name: name.clone(), uid: self.unique_id};
        self.uniques.insert(name, u.clone());
        u
    }
}
pub fn rename_expr(expr: TypedExpr<~str>) -> TypedExpr<Name> {
    let mut renamer = Renamer { uniques: ScopedMap::new(), unique_id: 1 };
    renamer.rename(expr)
}

pub fn rename_module(module: Module<~str>) -> Module<Name> {
    let mut renamer = Renamer { uniques: ScopedMap::new(), unique_id: 1 };
    let Module {
        name: name,
        classes : classes,
        dataDefinitions: data_definitions,
        typeDeclarations: typeDeclarations,
        bindings : bindings,
        instances: instances
    } = module;

    let data_definitions2 = data_definitions.move_iter().map(|data| {
        let DataDefinition {
            constructors : ctors,
            typ : typ,
            parameters : parameters
        } = data;
        DataDefinition {
            typ : typ,
            parameters : parameters,
            constructors : ctors.move_iter().map(|ctor| {
                let Constructor {
                    name : name,
                    typ : typ,
                    tag : tag,
                    arity : arity
                } = ctor;
                Constructor {
                    name : Name { name: name, uid: 0 },
                    typ : typ,
                    tag : tag,
                    arity : arity
                }
            }).collect()
        }
    }).collect();

    let instances2 = instances.move_iter().map(|instance| {
        let Instance {
            bindings : bindings,
            constraints : constraints,
            typ : typ,
            classname : classname
        } = instance;
        Instance {
            bindings : bindings.move_iter().map(|b| renamer.rename_binding(b)).collect(),
            constraints : constraints,
            typ : typ,
            classname : classname
        }
    }).collect();

    let bindings2 : ~[Binding<Name>] = bindings.move_iter().map(|b| renamer.rename_binding(b)).collect();

    Module {
        name: renamer.make_unique(name),
        classes : classes,
        dataDefinitions: data_definitions2,
        typeDeclarations: typeDeclarations,
        bindings : bindings2,
        instances: instances2
    }
}

<|endoftext|>


<commit_before>use futures::{Async, Future, Poll, Sink};
use futures::stream::Stream;
use futures::sink::Send;
use futures_state_stream::{StateStream, StreamEvent};

use native_tls::TlsConnector;

use std::io;
use std::net::ToSocketAddrs;

use tokio::net::{ConnectFuture, TcpStream};
use tokio_io::AsyncRead;
use tokio_tls::{ConnectAsync, TlsConnectorExt};

use imap_proto::{Request, RequestId, State};
use imap_proto::builders::command::Command;
use proto::{ImapCodec, ImapTransport, ResponseData};

pub mod builder {
    pub use imap_proto::builders::command::{CommandBuilder, FetchBuilderAttributes,
                                            FetchBuilderMessages, FetchBuilderModifiers,
                                            FetchCommand, FetchCommandAttributes,
                                            FetchCommandMessages};
}

pub struct Client {
    transport: ImapTransport,
    state: ClientState,
}

impl Client {
    pub fn connect(server: &str) -> ImapConnectFuture {
        let addr = (server, 993).to_socket_addrs().unwrap().next().unwrap();
        ImapConnectFuture::TcpConnecting(TcpStream::connect(&addr), server.to_string())
    }

    pub fn call(self, cmd: Command) -> ResponseStream {
        let Self { transport, mut state } = self;
        let request_id = state.request_ids.next().unwrap();
        let (cmd_bytes, next_state) = cmd.into_parts();
        let future = transport.send(Request(request_id.clone(), cmd_bytes));
        ResponseStream::new(future, state, request_id, next_state)
    }
}

pub struct ResponseStream {
    future: Option<Send<ImapTransport>>,
    transport: Option<ImapTransport>,
    state: Option<ClientState>,
    request_id: RequestId,
    next_state: Option<State>,
    done: bool,
}

impl ResponseStream {
    pub fn new(future: Send<ImapTransport>, state: ClientState,
               request_id: RequestId, next_state: Option<State>) -> Self {
        Self {
            future: Some(future),
            transport: None,
            state: Some(state),
            request_id: request_id,
            next_state: next_state,
            done: false,
        }
    }
}

impl StateStream for ResponseStream {
    type Item = ResponseData;
    type State = Client;
    type Error = io::Error;
    fn poll(&mut self) -> Poll<StreamEvent<Self::Item, Self::State>, Self::Error> {
        if self.future.is_some() {
            let mut future = self.future.take().unwrap();
            match future.poll() {
                Ok(Async::Ready(transport)) => {
                    self.transport = Some(transport);
                },
                Ok(Async::NotReady) => {
                    self.future = Some(future);
                    return Ok(Async::NotReady);
                },
                Err(e) => {
                    return Err(e);
                },
            }
        }
        if !self.transport.is_some() {
            return Ok(Async::NotReady);
        }
        let mut transport = self.transport.take().unwrap();
        if self.done {
            let mut state = self.state.take().unwrap();
            if self.next_state.is_some() {
                state.state = self.next_state.take().unwrap();
            }
            let client = Client { transport, state };
            return Ok(Async::Ready(StreamEvent::Done(client)));
        }
        match transport.poll() {
            Ok(Async::Ready(Some(rsp))) => {
                if let Some(req_id) = rsp.request_id() {
                    self.done = *req_id == self.request_id;
                };
                self.transport = Some(transport);
                return Ok(Async::Ready(StreamEvent::Next(rsp)));
            },
            Err(e) => {
                return Err(e);
            },
            _ => (),
        }
        self.transport = Some(transport);
        Ok(Async::NotReady)
    }
}

pub enum ImapConnectFuture {
    #[doc(hidden)] TcpConnecting(ConnectFuture, String),
    #[doc(hidden)] TlsHandshake(ConnectAsync<TcpStream>),
    #[doc(hidden)] ServerGreeting(Option<ImapTransport>),
}

impl Future for ImapConnectFuture {
    type Item = (Client, ResponseData);
    type Error = io::Error;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut new = None;
        if let ImapConnectFuture::TcpConnecting(ref mut future, ref domain) = *self {
            let stream = try_ready!(future.poll());
            let ctx = TlsConnector::builder().unwrap().build().unwrap();
            let future = ctx.connect_async(domain, stream);
            new = Some(ImapConnectFuture::TlsHandshake(future));
        }
        if new.is_some() {
            *self = new.take().unwrap();
        }
        if let ImapConnectFuture::TlsHandshake(ref mut future) = *self {
            let transport = try_ready!(future.map_err(|e| {
                io::Error::new(io::ErrorKind::Other, e)
            }).poll()).framed(ImapCodec::default());
            new = Some(ImapConnectFuture::ServerGreeting(Some(transport)));
        }
        if new.is_some() {
            *self = new.take().unwrap();
        }
        if let ImapConnectFuture::ServerGreeting(ref mut wrapped) = *self {
            let msg = try_ready!(wrapped.as_mut().unwrap().poll()).unwrap();
            return Ok(Async::Ready((Client {
                transport: wrapped.take().unwrap(),
                state: ClientState::new(),
            }, msg)));
        }
        Ok(Async::NotReady)
    }
}

pub struct ClientState {
    state: State,
    request_ids: IdGenerator,
}

impl ClientState {
    pub fn new() -> Self {
        Self {
            state: State::NotAuthenticated,
            request_ids: IdGenerator::new(),
        }
    }
}

impl Default for ClientState {
    fn default() -> Self {
        Self::new()
    }
}

pub struct IdGenerator {
    next: u64,
}

impl IdGenerator {
    pub fn new() -> Self {
        Self { next: 0 }
    }
}

impl Default for IdGenerator {
    fn default() -> Self {
        Self::new()
    }
}

impl Iterator for IdGenerator {
    type Item = RequestId;
    fn next(&mut self) -> Option<Self::Item> {
        self.next += 1;
        Some(RequestId(format!("A{:04}", self.next % 10_000)))
    }
}
<commit_msg>Remove unwrap() calls from Client::connect()<commit_after>use futures::{Async, Future, Poll, Sink};
use futures::stream::Stream;
use futures::sink::Send;
use futures_state_stream::{StateStream, StreamEvent};

use native_tls::TlsConnector;

use std::io;
use std::net::ToSocketAddrs;

use tokio::net::{ConnectFuture, TcpStream};
use tokio_io::AsyncRead;
use tokio_tls::{ConnectAsync, TlsConnectorExt};

use imap_proto::{Request, RequestId, State};
use imap_proto::builders::command::Command;
use proto::{ImapCodec, ImapTransport, ResponseData};

pub mod builder {
    pub use imap_proto::builders::command::{CommandBuilder, FetchBuilderAttributes,
                                            FetchBuilderMessages, FetchBuilderModifiers,
                                            FetchCommand, FetchCommandAttributes,
                                            FetchCommandMessages};
}

pub struct Client {
    transport: ImapTransport,
    state: ClientState,
}

impl Client {
    pub fn connect(server: &str) -> io::Result<ImapConnectFuture> {
        let addr = (server, 993).to_socket_addrs()?.next().ok_or_else(|| {
            io::Error::new(io::ErrorKind::Other, format!("no IP addresses found for {}", server))
        })?;
        Ok(ImapConnectFuture::TcpConnecting(TcpStream::connect(&addr), server.to_string()))
    }

    pub fn call(self, cmd: Command) -> ResponseStream {
        let Self { transport, mut state } = self;
        let request_id = state.request_ids.next().unwrap();
        let (cmd_bytes, next_state) = cmd.into_parts();
        let future = transport.send(Request(request_id.clone(), cmd_bytes));
        ResponseStream::new(future, state, request_id, next_state)
    }
}

pub struct ResponseStream {
    future: Option<Send<ImapTransport>>,
    transport: Option<ImapTransport>,
    state: Option<ClientState>,
    request_id: RequestId,
    next_state: Option<State>,
    done: bool,
}

impl ResponseStream {
    pub fn new(future: Send<ImapTransport>, state: ClientState,
               request_id: RequestId, next_state: Option<State>) -> Self {
        Self {
            future: Some(future),
            transport: None,
            state: Some(state),
            request_id: request_id,
            next_state: next_state,
            done: false,
        }
    }
}

impl StateStream for ResponseStream {
    type Item = ResponseData;
    type State = Client;
    type Error = io::Error;
    fn poll(&mut self) -> Poll<StreamEvent<Self::Item, Self::State>, Self::Error> {
        if self.future.is_some() {
            let mut future = self.future.take().unwrap();
            match future.poll() {
                Ok(Async::Ready(transport)) => {
                    self.transport = Some(transport);
                },
                Ok(Async::NotReady) => {
                    self.future = Some(future);
                    return Ok(Async::NotReady);
                },
                Err(e) => {
                    return Err(e);
                },
            }
        }
        if !self.transport.is_some() {
            return Ok(Async::NotReady);
        }
        let mut transport = self.transport.take().unwrap();
        if self.done {
            let mut state = self.state.take().unwrap();
            if self.next_state.is_some() {
                state.state = self.next_state.take().unwrap();
            }
            let client = Client { transport, state };
            return Ok(Async::Ready(StreamEvent::Done(client)));
        }
        match transport.poll() {
            Ok(Async::Ready(Some(rsp))) => {
                if let Some(req_id) = rsp.request_id() {
                    self.done = *req_id == self.request_id;
                };
                self.transport = Some(transport);
                return Ok(Async::Ready(StreamEvent::Next(rsp)));
            },
            Err(e) => {
                return Err(e);
            },
            _ => (),
        }
        self.transport = Some(transport);
        Ok(Async::NotReady)
    }
}

pub enum ImapConnectFuture {
    #[doc(hidden)] TcpConnecting(ConnectFuture, String),
    #[doc(hidden)] TlsHandshake(ConnectAsync<TcpStream>),
    #[doc(hidden)] ServerGreeting(Option<ImapTransport>),
}

impl Future for ImapConnectFuture {
    type Item = (Client, ResponseData);
    type Error = io::Error;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut new = None;
        if let ImapConnectFuture::TcpConnecting(ref mut future, ref domain) = *self {
            let stream = try_ready!(future.poll());
            let ctx = TlsConnector::builder().unwrap().build().unwrap();
            let future = ctx.connect_async(domain, stream);
            new = Some(ImapConnectFuture::TlsHandshake(future));
        }
        if new.is_some() {
            *self = new.take().unwrap();
        }
        if let ImapConnectFuture::TlsHandshake(ref mut future) = *self {
            let transport = try_ready!(future.map_err(|e| {
                io::Error::new(io::ErrorKind::Other, e)
            }).poll()).framed(ImapCodec::default());
            new = Some(ImapConnectFuture::ServerGreeting(Some(transport)));
        }
        if new.is_some() {
            *self = new.take().unwrap();
        }
        if let ImapConnectFuture::ServerGreeting(ref mut wrapped) = *self {
            let msg = try_ready!(wrapped.as_mut().unwrap().poll()).unwrap();
            return Ok(Async::Ready((Client {
                transport: wrapped.take().unwrap(),
                state: ClientState::new(),
            }, msg)));
        }
        Ok(Async::NotReady)
    }
}

pub struct ClientState {
    state: State,
    request_ids: IdGenerator,
}

impl ClientState {
    pub fn new() -> Self {
        Self {
            state: State::NotAuthenticated,
            request_ids: IdGenerator::new(),
        }
    }
}

impl Default for ClientState {
    fn default() -> Self {
        Self::new()
    }
}

pub struct IdGenerator {
    next: u64,
}

impl IdGenerator {
    pub fn new() -> Self {
        Self { next: 0 }
    }
}

impl Default for IdGenerator {
    fn default() -> Self {
        Self::new()
    }
}

impl Iterator for IdGenerator {
    type Item = RequestId;
    fn next(&mut self) -> Option<Self::Item> {
        self.next += 1;
        Some(RequestId(format!("A{:04}", self.next % 10_000)))
    }
}
<|endoftext|>


<commit_before>use num::Num;

/// A non-resizable (after creation) buffer.
pub struct ShiftRegister<T: Num + Copy> {
    qs: Box<[T]>,
}

impl<T: Num + Copy> ShiftRegister<T> {
    /// Create a new shift register.
    ///
    /// # Examples
    /// ```
    /// # use dsp::common::buffers::ShiftRegister;
    /// let sr: ShiftRegister<f32> = ShiftRegister::new(10);
    /// ```
    pub fn new(n: usize) -> Self {
        let mut qs = Vec::new();
        for _ in 0..n {
            qs.push(T::zero());
        }
        ShiftRegister { qs: qs.into_boxed_slice() }
    }

    /// Shift new simples into the register.
    ///
    /// ```
    /// # use dsp::common::buffers::ShiftRegister;
    /// let sr: ShiftRegister<f32> = ShiftRegister::new(10);
    /// ```
    pub fn push(&mut self, xs: &[T]) {
        if xs.len() >= self.len() {
            let pivot = xs.len() - self.len();
            let new_qs = &xs[pivot..];
            for i in 0..self.len() {
                self.qs[i] = new_qs[i];
            }
        } else {
            for i in 0..(self.len()-xs.len()) {
                self.qs[i] = self.qs[i+xs.len()];
            }
            let pivot = self.len()-xs.len();
            let mut xidx = 0;
            for i in pivot..self.len() {
                self.qs[i] = xs[xidx];
                xidx += 1;
            }
        }
    }

    /// Returns the length of the shift registers.
    ///
    /// # Examples
    /// ```
    /// # use dsp::common::buffers::ShiftRegister;
    /// let sr = ShiftRegister::<i32>::new(10);
    /// assert_eq!(10, sr.len())
    /// ```
    pub fn len(&self) -> usize {
        self.qs.len()
    }

}

impl<T: Num + Copy> AsRef<[T]> for ShiftRegister<T> {
    fn as_ref(&self) -> &[T] {
        self.qs.as_ref()
    }
}

#[cfg(test)]
mod test {
    use ::common::buffers::ShiftRegister;

    #[test]
    fn test_shift_register_multipart() {
        let mut sr = ShiftRegister::<i32>::new(5);
        sr.push([0,1,2,3,4].as_ref());
        sr.push([5].as_ref());
        assert_eq!(sr.as_ref(),[1,2,3,4,5].as_ref())
    }
}
<commit_msg>Rename ShifRegister to ShiftBuf<commit_after>use num::Num;

/// A non-resizable (after creation) buffer.
pub struct ShiftBuf<T: Num + Copy> {
    qs: Box<[T]>,
}

impl<T: Num + Copy> ShiftBuf<T> {
    /// Create a new shift register.
    ///
    /// # Examples
    /// ```
    /// # use dsp::common::buffers::ShiftBuf;
    /// let buf: ShiftBuf<f32> = ShiftBuf::new(10);
    /// ```
    pub fn new(n: usize) -> Self {
        let mut qs = Vec::new();
        for _ in 0..n {
            qs.push(T::zero());
        }
        ShiftBuf { qs: qs.into_boxed_slice() }
    }

    /// Shift new simples into the register.
    ///
    /// ```
    /// # use dsp::common::buffers::ShiftBuf;
    /// let buf: ShiftBuf<f32> = ShiftBuf::new(10);
    /// ```
    pub fn push(&mut self, xs: &[T]) {
        if xs.len() >= self.len() {
            let pivot = xs.len() - self.len();
            let new_qs = &xs[pivot..];
            for i in 0..self.len() {
                self.qs[i] = new_qs[i];
            }
        } else {
            for i in 0..(self.len()-xs.len()) {
                self.qs[i] = self.qs[i+xs.len()];
            }
            let pivot = self.len()-xs.len();
            let mut xidx = 0;
            for i in pivot..self.len() {
                self.qs[i] = xs[xidx];
                xidx += 1;
            }
        }
    }

    /// Returns the length of the shift registers.
    ///
    /// # Examples
    /// ```
    /// # use dsp::common::buffers::ShiftBuf;
    /// let buf = ShiftBuf::<i32>::new(10);
    /// assert_eq!(10, buf.len())
    /// ```
    pub fn len(&self) -> usize {
        self.qs.len()
    }

}

impl<T: Num + Copy> AsRef<[T]> for ShiftBuf<T> {
    fn as_ref(&self) -> &[T] {
        self.qs.as_ref()
    }
}

#[cfg(test)]
mod test {
    use ::common::buffers::ShiftBuf;

    #[test]
    fn test_shift_register_multipart() {
        let mut buf = ShiftBuf::<i32>::new(5);
        buf.push([0,1,2,3,4].as_ref());
        buf.push([5].as_ref());
        assert_eq!(buf.as_ref(),[1,2,3,4,5].as_ref())
    }
}
<|endoftext|>