<commit_before>use crate::error::ParseMessageError;
use crate::structs;
use std::fmt;
use std::str::FromStr;

#[derive(Debug)]
pub enum Pw {
    Uid(u64),
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Sp {
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Gr {
    Gid(u64),
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Ent {
    Set(u32),
    Get(u32),
    End(u32),
}

pub struct DividedMessage {
    pub cont: bool,
    pub message: String,
}

impl DividedMessage {
    #[allow(dead_code)]
    pub fn new(msg: &str, size: usize) -> Vec<Self> {
        let mut msgs = vec![];
        let mut idx = 0;
        while idx + size < msg.len() {
            msgs.push(Self { cont: true,
                             message: msg[idx..idx + size].to_owned() });
            idx += size
        }
        msgs.push(Self { cont: false,
                         message: msg[idx..msg.len()].to_owned() });
        msgs
    }
}

impl fmt::Display for DividedMessage {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}:{}", if self.cont { 1 } else { 0 }, self.message)
    }
}

impl FromStr for DividedMessage {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if let Some(msg) = s.strip_prefix("0:") {
            Ok(Self { cont: false,
                      message: msg.to_owned() })
        } else if let Some(msg) = s.strip_prefix("1:") {
            Ok(Self { cont: true,
                      message: msg.to_owned() })
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

#[derive(Debug)]
pub enum ClientMessage {
    Cont,
    Key { user: String },
    Pam { user: String },
    CleanUp,
    RateLimit,
    SectorGroups,
    Pw(Pw),
    Sp(Sp),
    Gr(Gr),
}

#[allow(dead_code)]
#[derive(Debug)]
pub enum DaemonMessage {
    Success,
    Error {
        message: String,
    },
    Key {
        keys: String,
    },
    Pam {
        result: bool,
    },
    RateLimit {
        limit: usize,
        remaining: usize,
        reset: usize,
    },
    SectorGroups {
        sectors: Vec<structs::SectorGroup>,
    },
    Pw {
        login: String,
        uid: u64,
        gid: u64,
        home: String,
        sh: String,
    },
    Sp {
        login: String,
        pass: String,
    },
    Gr {
        sector: structs::SectorGroup,
    },
}

impl fmt::Display for Ent {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Ent::Set(pid) => write!(f, "set|{}", pid),
            Ent::Get(pid) => write!(f, "get|{}", pid),
            Ent::End(pid) => write!(f, "end|{}", pid),
        }
    }
}

impl fmt::Display for Pw {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Pw::Uid(uid) => write!(f, "uid={}", uid),
            Pw::Nam(name) => write!(f, "name={}", name),
            Pw::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for Sp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Sp::Nam(name) => write!(f, "name={}", name),
            Sp::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for Gr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Gr::Gid(gid) => write!(f, "gid={}", gid),
            Gr::Nam(name) => write!(f, "name={}", name),
            Gr::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for ClientMessage {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ClientMessage::Cont => write!(f, "c:cont"),
            ClientMessage::Key { user } => write!(f, "c:key:{}", user),
            ClientMessage::Pam { user } => write!(f, "c:pam:{}", user),
            ClientMessage::CleanUp => write!(f, "c:cleanup"),
            ClientMessage::RateLimit => write!(f, "c:ratelimit"),
            ClientMessage::SectorGroups => write!(f, "c:sectors"),
            ClientMessage::Pw(pw) => write!(f, "c:pw:{}", pw),
            ClientMessage::Sp(sp) => write!(f, "c:sp:{}", sp),
            ClientMessage::Gr(gr) => write!(f, "c:gr:{}", gr),
        }
    }
}

impl fmt::Display for DaemonMessage {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            DaemonMessage::Error { message } => write!(f, "d:error:{}", message),
            DaemonMessage::Success => write!(f, "d:success"),
            DaemonMessage::Key { keys } => write!(f, "d:key:{}", keys),
            DaemonMessage::Pam { result } => write!(f, "d:pam:{}", result),
            DaemonMessage::RateLimit { limit,
                                       remaining,
                                       reset, } => write!(f, "d:ratelimit:{}:{}:{}", limit, remaining, reset),
            DaemonMessage::SectorGroups { sectors } => {
                let ss: Vec<String> = sectors.iter().map(|s| s.to_string()).collect();
                write!(f, "d:sectors:{}", ss.join("\n"))
            }
            DaemonMessage::Pw { login,
                                uid,
                                gid,
                                home,
                                sh, } => write!(f, "d:pw:{}:{}:{}:{}:{}", login, uid, gid, home, sh),
            DaemonMessage::Sp { login, pass } => write!(f, "d:sp:{}:{}", login, pass),
            DaemonMessage::Gr { sector } => write!(f, "d:gr:{}", sector),
        }
    }
}

impl FromStr for Ent {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if let Some(msg) = s.strip_prefix("set|") {
            Ok(Ent::Set(msg.parse::<u32>().unwrap()))
        } else if let Some(msg) = s.strip_prefix("get|") {
            Ok(Ent::Get(msg.parse::<u32>().unwrap()))
        } else if let Some(msg) = s.strip_prefix("end|") {
            Ok(Ent::End(msg.parse::<u32>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Pw {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if let Some(msg) = s.strip_prefix("uid=") {
            Ok(Pw::Uid(msg.parse::<u64>().unwrap()))
        } else if let Some(msg) = s.strip_prefix("name=") {
            Ok(Pw::Nam(String::from(msg)))
        } else if let Some(msg) = s.strip_prefix("ent=") {
            Ok(Pw::Ent(msg.parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Sp {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("name=") {
            Ok(Sp::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Sp::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Gr {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("gid=") {
            Ok(Gr::Gid(s.get(4..).unwrap_or_default().parse::<u64>().unwrap()))
        } else if s.starts_with("name=") {
            Ok(Gr::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Gr::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for ClientMessage {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("c:cont") {
            Ok(ClientMessage::Cont)
        } else if s.starts_with("c:key:") {
            Ok(ClientMessage::Key { user: String::from(s.get(6..).unwrap_or_default()) })
        } else if s.starts_with("c:pam:") {
            Ok(ClientMessage::Pam { user: String::from(s.get(6..).unwrap_or_default()) })
        } else if s == "c:cleanup" {
            Ok(ClientMessage::CleanUp)
        } else if s == "c:ratelimit" {
            Ok(ClientMessage::RateLimit)
        } else if s == "c:sectors" {
            Ok(ClientMessage::SectorGroups)
        } else if s.starts_with("c:pw:") {
            Ok(ClientMessage::Pw(s.get(5..).unwrap_or_default().parse::<Pw>()?))
        } else if s.starts_with("c:sp:") {
            Ok(ClientMessage::Sp(s.get(5..).unwrap_or_default().parse::<Sp>()?))
        } else if s.starts_with("c:gr:") {
            Ok(ClientMessage::Gr(s.get(5..).unwrap_or_default().parse::<Gr>()?))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for DaemonMessage {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("d:key:") {
            Ok(DaemonMessage::Key { keys: String::from(s.get(6..).unwrap_or_default()) })
        } else if s.starts_with("d:pam:") {
            Ok(DaemonMessage::Pam { result: FromStr::from_str(s.get(6..).unwrap_or("false")).unwrap_or(false) })
        } else if s == "d:success" {
            Ok(DaemonMessage::Success)
        } else if s.starts_with("d:ratelimit:") {
            let fields: Vec<String> = s.get(12..)
                                       .unwrap_or_default()
                                       .split(':')
                                       .map(|s| s.to_string())
                                       .collect();
            if fields.len() < 3 {
                return Err(ParseMessageError::ParseDaemonMessageError);
            }
            let limit = fields[0].clone().parse().unwrap_or(0);
            let remaining = fields[1].clone().parse().unwrap_or(0);
            let reset = fields[2].clone().parse().unwrap_or(0);
            Ok(DaemonMessage::RateLimit { limit,
                                          remaining,
                                          reset })
        } else if s.starts_with("d:sectors:") {
            let sectors = s.get(10..)
                           .unwrap_or_default()
                           .split('\n')
                           .filter_map(|l| l.parse::<structs::SectorGroup>().ok())
                           .collect();
            Ok(DaemonMessage::SectorGroups { sectors })
        } else if s.starts_with("d:pw:") {
            let fields: Vec<String> = s.get(5..)
                                       .unwrap_or_default()
                                       .split(':')
                                       .map(|s| s.to_string())
                                       .collect();
            if fields.len() < 5 {
                return Err(ParseMessageError::ParseDaemonMessageError);
            }
            let login: String = fields[0].clone();
            let home: String = fields[3].clone();
            let sh: String = fields[4].clone();
            match (fields[1].parse::<u64>(), fields[2].parse::<u64>()) {
                (Ok(uid), Ok(gid)) => Ok(DaemonMessage::Pw { login,
                                                             uid,
                                                             gid,
                                                             home,
                                                             sh }),
                _ => Err(ParseMessageError::ParseDaemonMessageError),
            }
        } else if s.starts_with("d:sp:") {
            let fields: Vec<String> = s.get(5..)
                                       .unwrap_or_default()
                                       .split(':')
                                       .map(|s| s.to_string())
                                       .collect();
            if fields.len() < 2 {
                return Err(ParseMessageError::ParseDaemonMessageError);
            }
            Ok(DaemonMessage::Sp { login: fields[0].clone(),
                                   pass: fields[1].clone() })
        } else if s.starts_with("d:gr:") {
            match s.get(5..).unwrap_or_default().parse::<structs::SectorGroup>() {
                Ok(sector) => Ok(DaemonMessage::Gr { sector }),
                _ => Err(ParseMessageError::ParseDaemonMessageError),
            }
        } else {
            Err(ParseMessageError::ParseDaemonMessageError)
        }
    }
}
<commit_msg>Remove manual strips in Sp<commit_after>use crate::error::ParseMessageError;
use crate::structs;
use std::fmt;
use std::str::FromStr;

#[derive(Debug)]
pub enum Pw {
    Uid(u64),
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Sp {
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Gr {
    Gid(u64),
    Nam(String),
    Ent(Ent),
}

#[derive(Debug)]
pub enum Ent {
    Set(u32),
    Get(u32),
    End(u32),
}

pub struct DividedMessage {
    pub cont: bool,
    pub message: String,
}

impl DividedMessage {
    #[allow(dead_code)]
    pub fn new(msg: &str, size: usize) -> Vec<Self> {
        let mut msgs = vec![];
        let mut idx = 0;
        while idx + size < msg.len() {
            msgs.push(Self { cont: true,
                             message: msg[idx..idx + size].to_owned() });
            idx += size
        }
        msgs.push(Self { cont: false,
                         message: msg[idx..msg.len()].to_owned() });
        msgs
    }
}

impl fmt::Display for DividedMessage {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}:{}", if self.cont { 1 } else { 0 }, self.message)
    }
}

impl FromStr for DividedMessage {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if let Some(msg) = s.strip_prefix("0:") {
            Ok(Self { cont: false,
                      message: msg.to_owned() })
        } else if let Some(msg) = s.strip_prefix("1:") {
            Ok(Self { cont: true,
                      message: msg.to_owned() })
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

#[derive(Debug)]
pub enum ClientMessage {
    Cont,
    Key { user: String },
    Pam { user: String },
    CleanUp,
    RateLimit,
    SectorGroups,
    Pw(Pw),
    Sp(Sp),
    Gr(Gr),
}

#[allow(dead_code)]
#[derive(Debug)]
pub enum DaemonMessage {
    Success,
    Error {
        message: String,
    },
    Key {
        keys: String,
    },
    Pam {
        result: bool,
    },
    RateLimit {
        limit: usize,
        remaining: usize,
        reset: usize,
    },
    SectorGroups {
        sectors: Vec<structs::SectorGroup>,
    },
    Pw {
        login: String,
        uid: u64,
        gid: u64,
        home: String,
        sh: String,
    },
    Sp {
        login: String,
        pass: String,
    },
    Gr {
        sector: structs::SectorGroup,
    },
}

impl fmt::Display for Ent {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Ent::Set(pid) => write!(f, "set|{}", pid),
            Ent::Get(pid) => write!(f, "get|{}", pid),
            Ent::End(pid) => write!(f, "end|{}", pid),
        }
    }
}

impl fmt::Display for Pw {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Pw::Uid(uid) => write!(f, "uid={}", uid),
            Pw::Nam(name) => write!(f, "name={}", name),
            Pw::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for Sp {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Sp::Nam(name) => write!(f, "name={}", name),
            Sp::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for Gr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Gr::Gid(gid) => write!(f, "gid={}", gid),
            Gr::Nam(name) => write!(f, "name={}", name),
            Gr::Ent(ent) => write!(f, "ent={}", ent),
        }
    }
}

impl fmt::Display for ClientMessage {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ClientMessage::Cont => write!(f, "c:cont"),
            ClientMessage::Key { user } => write!(f, "c:key:{}", user),
            ClientMessage::Pam { user } => write!(f, "c:pam:{}", user),
            ClientMessage::CleanUp => write!(f, "c:cleanup"),
            ClientMessage::RateLimit => write!(f, "c:ratelimit"),
            ClientMessage::SectorGroups => write!(f, "c:sectors"),
            ClientMessage::Pw(pw) => write!(f, "c:pw:{}", pw),
            ClientMessage::Sp(sp) => write!(f, "c:sp:{}", sp),
            ClientMessage::Gr(gr) => write!(f, "c:gr:{}", gr),
        }
    }
}

impl fmt::Display for DaemonMessage {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            DaemonMessage::Error { message } => write!(f, "d:error:{}", message),
            DaemonMessage::Success => write!(f, "d:success"),
            DaemonMessage::Key { keys } => write!(f, "d:key:{}", keys),
            DaemonMessage::Pam { result } => write!(f, "d:pam:{}", result),
            DaemonMessage::RateLimit { limit,
                                       remaining,
                                       reset, } => write!(f, "d:ratelimit:{}:{}:{}", limit, remaining, reset),
            DaemonMessage::SectorGroups { sectors } => {
                let ss: Vec<String> = sectors.iter().map(|s| s.to_string()).collect();
                write!(f, "d:sectors:{}", ss.join("\n"))
            }
            DaemonMessage::Pw { login,
                                uid,
                                gid,
                                home,
                                sh, } => write!(f, "d:pw:{}:{}:{}:{}:{}", login, uid, gid, home, sh),
            DaemonMessage::Sp { login, pass } => write!(f, "d:sp:{}:{}", login, pass),
            DaemonMessage::Gr { sector } => write!(f, "d:gr:{}", sector),
        }
    }
}

impl FromStr for Ent {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if let Some(msg) = s.strip_prefix("set|") {
            Ok(Ent::Set(msg.parse::<u32>().unwrap()))
        } else if let Some(msg) = s.strip_prefix("get|") {
            Ok(Ent::Get(msg.parse::<u32>().unwrap()))
        } else if let Some(msg) = s.strip_prefix("end|") {
            Ok(Ent::End(msg.parse::<u32>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Pw {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if let Some(msg) = s.strip_prefix("uid=") {
            Ok(Pw::Uid(msg.parse::<u64>().unwrap()))
        } else if let Some(msg) = s.strip_prefix("name=") {
            Ok(Pw::Nam(String::from(msg)))
        } else if let Some(msg) = s.strip_prefix("ent=") {
            Ok(Pw::Ent(msg.parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Sp {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if let Some(msg) = s.strip_prefix("name=") {
            Ok(Sp::Nam(String::from(msg)))
        } else if let Some(msg) = s.strip_prefix("ent=") {
            Ok(Sp::Ent(msg.parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for Gr {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("gid=") {
            Ok(Gr::Gid(s.get(4..).unwrap_or_default().parse::<u64>().unwrap()))
        } else if s.starts_with("name=") {
            Ok(Gr::Nam(String::from(s.get(5..).unwrap_or_default())))
        } else if s.starts_with("ent=") {
            Ok(Gr::Ent(s.get(4..).unwrap_or_default().parse::<Ent>().unwrap()))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for ClientMessage {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("c:cont") {
            Ok(ClientMessage::Cont)
        } else if s.starts_with("c:key:") {
            Ok(ClientMessage::Key { user: String::from(s.get(6..).unwrap_or_default()) })
        } else if s.starts_with("c:pam:") {
            Ok(ClientMessage::Pam { user: String::from(s.get(6..).unwrap_or_default()) })
        } else if s == "c:cleanup" {
            Ok(ClientMessage::CleanUp)
        } else if s == "c:ratelimit" {
            Ok(ClientMessage::RateLimit)
        } else if s == "c:sectors" {
            Ok(ClientMessage::SectorGroups)
        } else if s.starts_with("c:pw:") {
            Ok(ClientMessage::Pw(s.get(5..).unwrap_or_default().parse::<Pw>()?))
        } else if s.starts_with("c:sp:") {
            Ok(ClientMessage::Sp(s.get(5..).unwrap_or_default().parse::<Sp>()?))
        } else if s.starts_with("c:gr:") {
            Ok(ClientMessage::Gr(s.get(5..).unwrap_or_default().parse::<Gr>()?))
        } else {
            Err(ParseMessageError::ParseClientMessageError)
        }
    }
}

impl FromStr for DaemonMessage {
    type Err = ParseMessageError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s.starts_with("d:key:") {
            Ok(DaemonMessage::Key { keys: String::from(s.get(6..).unwrap_or_default()) })
        } else if s.starts_with("d:pam:") {
            Ok(DaemonMessage::Pam { result: FromStr::from_str(s.get(6..).unwrap_or("false")).unwrap_or(false) })
        } else if s == "d:success" {
            Ok(DaemonMessage::Success)
        } else if s.starts_with("d:ratelimit:") {
            let fields: Vec<String> = s.get(12..)
                                       .unwrap_or_default()
                                       .split(':')
                                       .map(|s| s.to_string())
                                       .collect();
            if fields.len() < 3 {
                return Err(ParseMessageError::ParseDaemonMessageError);
            }
            let limit = fields[0].clone().parse().unwrap_or(0);
            let remaining = fields[1].clone().parse().unwrap_or(0);
            let reset = fields[2].clone().parse().unwrap_or(0);
            Ok(DaemonMessage::RateLimit { limit,
                                          remaining,
                                          reset })
        } else if s.starts_with("d:sectors:") {
            let sectors = s.get(10..)
                           .unwrap_or_default()
                           .split('\n')
                           .filter_map(|l| l.parse::<structs::SectorGroup>().ok())
                           .collect();
            Ok(DaemonMessage::SectorGroups { sectors })
        } else if s.starts_with("d:pw:") {
            let fields: Vec<String> = s.get(5..)
                                       .unwrap_or_default()
                                       .split(':')
                                       .map(|s| s.to_string())
                                       .collect();
            if fields.len() < 5 {
                return Err(ParseMessageError::ParseDaemonMessageError);
            }
            let login: String = fields[0].clone();
            let home: String = fields[3].clone();
            let sh: String = fields[4].clone();
            match (fields[1].parse::<u64>(), fields[2].parse::<u64>()) {
                (Ok(uid), Ok(gid)) => Ok(DaemonMessage::Pw { login,
                                                             uid,
                                                             gid,
                                                             home,
                                                             sh }),
                _ => Err(ParseMessageError::ParseDaemonMessageError),
            }
        } else if s.starts_with("d:sp:") {
            let fields: Vec<String> = s.get(5..)
                                       .unwrap_or_default()
                                       .split(':')
                                       .map(|s| s.to_string())
                                       .collect();
            if fields.len() < 2 {
                return Err(ParseMessageError::ParseDaemonMessageError);
            }
            Ok(DaemonMessage::Sp { login: fields[0].clone(),
                                   pass: fields[1].clone() })
        } else if s.starts_with("d:gr:") {
            match s.get(5..).unwrap_or_default().parse::<structs::SectorGroup>() {
                Ok(sector) => Ok(DaemonMessage::Gr { sector }),
                _ => Err(ParseMessageError::ParseDaemonMessageError),
            }
        } else {
            Err(ParseMessageError::ParseDaemonMessageError)
        }
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "color")]
use ansi_term::Colour::{Red, Green, Blue, White};

pub enum CliMessage<'a> {
    Account,
    Action,
    Actions,
    ActionId(&'a str),
    Failure,
    JsonResponse,
    Regions,
    Sizes,
    Images,
    SshKeys,
    Dropets,
    Droplet(&'a str),
    DropletKernels(&'a str),
    DropletSnapshots(&'a str),
    DropletBackups(&' str),
    DropletActions(&'a str),
    DeleteDroplet(&'a str),
    DropletNeighbors(&'a str),
    DisableBackups(&'a str),
    RebootDroplet(&'a str),
    PowerCycleDroplet(&'a str),
    ShutdownDroplet(&'a str),
    PowerOffDroplet(&'a str),
    PowerOnDroplet(&'a str),
    RestoreDroplet(&'a str, &'a str),
    ResizeDroplet(&'a str, &'a str, bool),
    RebuildDroplet(&'a str, &'a str),
    RenameDroplet(&'a str, &'a str),
    ChangeKernel(&'a str, &'a str),
    EnableIpv6(&'a str),
    EnablePrivateNetworking(&'a str),
    SnapshotDroplet(&'a str),
    DropletAction(&'a str, &'a str),
    UpgradeDroplet(&'a str),
    Kernel,
    Domains,
    Request(&'a str),
    Success,
    Token(&'a str),
    ImageActions(&'a str),
    Image(&'a str),
    UpdateImage(&'a str),
    DeleteImage(&'a str),
    ConvertImage(&'a str),
    TransferImage(&'a str, &'a str),
    ImageAction(&'a str, &'a str),
}

impl<'a> CliMessage<'a> {
    #[cfg(feature="color")]
    pub fn display(&self) {
        match *self {
            CliMessage::Account => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying account information..."));
            },
            CliMessage::Action => {
                print!("{}", Blue.bold().paint("::"));
                println!(" {}", White.bold().paint("Displaying account action...\n\t") );
            },
            CliMessage::Actions => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying all account actions..."));
            },
            CliMessage::ActionId(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying account action ID "));
                print!("{}...", White.bold().underline().paint(id));
            },
            CliMessage::Failure => {
                println!("{}", Red.paint("Failed"));
            },
            CliMessage::JsonResponse => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying JSON response from DigitalOcean...\n"));
            },
            CliMessage::Request(req) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying sent request...\n\t"));
                println!("{}\n", req);
            },
            CliMessage::Success => {
                println!("{}", Green.paint("Success"));
            },
            CliMessage::Token(tok) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying account token...\n\t"));
                println!("{}\n", tok);
            },
            CliMessage::Regions => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying all regions..."));
            },
            CliMessage::Sizes => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying all sizes..."));
            },
            CliMessage::Images => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying all images..."));
            },
            CliMessage::SshKeys => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying all SSH keys..."));
            },
            CliMessage::Dropets => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying all droplets..."));
            },
            CliMessage::Domains => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying all domains..."));
            },
            CliMessage::ImageActions(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying all actions for image ID "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::Image(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying image "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::UpdateImage(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Updating image "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::DeleteImage(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Deleting image "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::ConvertImage(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Converting image "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::TransferImage(id, region) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Transferring image "));
                print!("{}", White.bold().underline().paint(id));
                print!(" {}", White.bold().paint("to region "));
                print!("{}", White.bold().underline().paint(region));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::ImageAction(id, a_id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying action "));
                print!("{}", White.bold().underline().paint(a_id));
                print!(" {}", White.bold().paint("for image "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::Droplet(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::DropletKernels(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying all droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!(" {}", White.bold().paint("kernels..."));
            },
            CliMessage::DropletSnapshots(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying all droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!(" {}", White.bold().paint("snapshots..."));
            },
            CliMessage::DropletBackups(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying all backups for droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::DropletActions(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying all actions for droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::DeleteDroplet(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Deleting droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::DropletNeighbors(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying all neighbors for droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::DisableBackups(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Disabling backups for droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::RebootDroplet(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Rebooting droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::PowerCycleDroplet(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Power-cycling droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::ShutdownDroplet(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Shutting down droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::PowerOffDroplet(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Powering off down droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::PowerOnDroplet(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Powering on down droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::RestoreDroplet(id, img) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Restoring droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!(" {}", White.bold().paint("to "));
                print!("{}", White.bold().underline().paint(img));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::RebuildDroplet(id, img) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Rebuilding droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!(" {}", White.bold().paint("with "));
                print!("{}", White.bold().underline().paint(img));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::RenameDroplet(id, name) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Renaming droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!(" {}", White.bold().paint("to "));
                print!("{}", White.bold().underline().paint(name));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::ChangeKernel(id, kernel) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Changing the kernel of droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!(" {}", White.bold().paint("to "));
                print!("{}", White.bold().underline().paint(kernel));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::EnableIpv6(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Enabling IPv6 for droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::EnablePrivateNetworking(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Enabling private networking for droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::SnapshotDroplet(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Taking a snapshot of droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::UpgradeDroplet(id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Upgrading droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::Kernel => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying kerenl..."));
            },
            CliMessage::DropletAction(id, a_id) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Displaying action "));
                print!("{}", White.bold().underline().paint(a_id));
                print!(" {}", White.bold().paint("for droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("..."));
            },
            CliMessage::ResizeDroplet(id, size, disk) => {
                print!("{}", Blue.bold().paint("::"));
                print!(" {}", White.bold().paint("Resizing "));
                if disk {
                    print!("{}", White.bold().paint("the disk for "));
                }
                print!("{}", White.bold().paint("droplet "));
                print!("{}", White.bold().underline().paint(id));
                print!("{}", White.bold().paint("to "));
                print!("{}", White.bold().underline().paint(size));
                print!("{}", White.bold().paint("..."));
            },
        }
    }

    #[cfg(not(feature="color"))]
    pub fn display(&self) {
        print!("::");
        match *self {
            CliMessage::Account => {
                print!(" Displaying account information...");
            },
            CliMessage::Action => {
                println!(" Displaying account action...\n\t");
            },
            CliMessage::Actions => {
                print!(" Displaying all account actions...\n");
            },
            CliMessage::ActionId(id) => {
                print!(" Displaying account action ID {}...", id);
            },
            CliMessage::Failure => {
                println!("Failed");
            },
            CliMessage::JsonResponse => {
                print!(" Displaying JSON response from DigitalOcean...\n");
            },
            CliMessage::Request(req) => {
                println!(" Displaying sent request...\n\t{}\n", req);
            },
            CliMessage::Success => {
                println!("Success");
            },
            CliMessage::Token(tok) => {
                println!(" Displaying account token...\n\t{}\n", tok);
            },
            CliMessage::Regions => {
                print!(":: Displaying all regions...");
            },
            CliMessage::Sizes => {
                print!("::Displaying all sizes...");
            },
            CliMessage::Images => {
                print!("::Displaying all images...");
            },
            CliMessage::SshKeys => {
                print!(":: Displaying all SSH keys...");
            },
            CliMessage::Dropets => {
                print!(":: Displaying all droplets...");
            },
            CliMessage::Domains => {
                print!(":: Displaying all domains...");
            },
            CliMessage::ImageActions(id) => {
                print!(":: Displaying all actions for image {}...", id);
            },
            CliMessage::Image(id) => {
                print!(":: Displaying image {}...", id);
            },
            CliMessage::UpdateImage(id) => {
                print!(":: Updating image {}...", id);
            },
            CliMessage::DeleteImage(id) => {
                print!(":: Deleting image {}...", id);
            },
            CliMessage::ConvertImage(id) => {
                print!(":: Converting image {}...", id);
            },
            CliMessage::TransferImage(id, region) => {
                print!(":: Transferring image {} to region {}...", id, region);
            },
            CliMessage::ImageAction(id, a_id) => {
                print!(":: Displaying action {} for image {}...", a_id, id);
            }
        }
    }
}<commit_msg>style(messages): change style for readability<commit_after>#[cfg(feature = "color")]
use ansi_term::Colour::{Red, Green, Blue, White};

pub enum CliMessage<'a> {
    Account,
    Action,
    Actions,
    ActionId(&'a str),
    Failure,
    JsonResponse,
    Regions,
    Sizes,
    Images,
    SshKeys,
    Dropets,
    Droplet(&'a str),
    DropletKernels(&'a str),
    DropletSnapshots(&'a str),
    DropletBackups(&' str),
    DropletActions(&'a str),
    DeleteDroplet(&'a str),
    DropletNeighbors(&'a str),
    DisableBackups(&'a str),
    RebootDroplet(&'a str),
    PowerCycleDroplet(&'a str),
    ShutdownDroplet(&'a str),
    PowerOffDroplet(&'a str),
    PowerOnDroplet(&'a str),
    RestoreDroplet(&'a str, &'a str),
    ResizeDroplet(&'a str, &'a str, bool),
    RebuildDroplet(&'a str, &'a str),
    RenameDroplet(&'a str, &'a str),
    ChangeKernel(&'a str, &'a str),
    EnableIpv6(&'a str),
    EnablePrivateNetworking(&'a str),
    SnapshotDroplet(&'a str),
    DropletAction(&'a str, &'a str),
    UpgradeDroplet(&'a str),
    Kernel,
    Domains,
    Request(&'a str),
    Success,
    Token(&'a str),
    ImageActions(&'a str),
    Image(&'a str),
    UpdateImage(&'a str),
    DeleteImage(&'a str),
    ConvertImage(&'a str),
    TransferImage(&'a str, &'a str),
    ImageAction(&'a str, &'a str),
}

impl<'a> CliMessage<'a> {
    #[cfg(feature="color")]
    pub fn display(&self) {
        match *self {
            CliMessage::Account => {
                print!("{} {}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying account information..."));
            },
            CliMessage::Action => {
                println!("{} {}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying account action...\n\t"));
            },
            CliMessage::Actions => {
                print!("{} {}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying all account actions..."));
            },
            CliMessage::ActionId(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying account action ID"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::Failure => {
                println!("{}", Red.paint("Failed"));
            },
            CliMessage::JsonResponse => {
                print!("{} {}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying JSON response from DigitalOcean...\n"));
            },
            CliMessage::Request(req) => {
                println!("{} {}\n\t{}\n",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying sent request..."),
                    req);
            },
            CliMessage::Success => {
                println!("{}", Green.paint("Success"));
            },
            CliMessage::Token(tok) => {
                println!("{} {}\n\t{}\n",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying account token...\n\t"),
                    tok);
            },
            CliMessage::Regions => {
                print!("{} {}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying all regions..."));
            },
            CliMessage::Sizes => {
                print!("{} {}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying all sizes..."));
            },
            CliMessage::Images => {
                print!("{} {}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying all images..."));
            },
            CliMessage::SshKeys => {
                print!("{} {}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying all SSH keys..."));
            },
            CliMessage::Dropets => {
                print!("{} {}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying all droplets..."));
            },
            CliMessage::Domains => {
                print!("{} {}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying all domains..."));
            },
            CliMessage::ImageActions(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying all actions for image ID"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::Image(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying image"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::UpdateImage(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Updating image"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::DeleteImage(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Deleting image"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::ConvertImage(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Converting image"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::TransferImage(id, region) => {
                print!("{} {} {} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Transferring image"),
                    White.bold().underline().paint(id),
                    White.bold().paint("to region"),
                    White.bold().underline().paint(region),
                    White.bold().paint("..."));
            },
            CliMessage::ImageAction(id, a_id) => {
                print!("{} {} {} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying action"),
                    White.bold().underline().paint(a_id),
                    White.bold().paint("for image"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::Droplet(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::DropletKernels(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying all droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("kernels..."));
            },
            CliMessage::DropletSnapshots(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying all droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("snapshots..."));
            },
            CliMessage::DropletBackups(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying all backups for droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::DropletActions(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying all actions for droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::DeleteDroplet(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Deleting droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::DropletNeighbors(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying all neighbors for droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::DisableBackups(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Disabling backups for droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::RebootDroplet(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Rebooting droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::PowerCycleDroplet(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Power-cycling droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::ShutdownDroplet(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Shutting down droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::PowerOffDroplet(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Powering off down droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::PowerOnDroplet(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Powering on down droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::RestoreDroplet(id, img) => {
                print!("{} {} {} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Restoring droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("to"),
                    White.bold().underline().paint(img),
                    White.bold().paint("..."));
            },
            CliMessage::RebuildDroplet(id, img) => {
                print!("{} {} {} {} {}{}",
                    Blue.bold().paint("::"));
                    White.bold().paint("Rebuilding droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("with"),
                    White.bold().underline().paint(img),
                    White.bold().paint("..."));
            },
            CliMessage::RenameDroplet(id, name) => {
                print!("{} {} {} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Renaming droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("to"),
                    White.bold().underline().paint(name),
                    White.bold().paint("..."));
            },
            CliMessage::ChangeKernel(id, kernel) => {
                print!("{} {} {} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Changing the kernel of droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("to"),
                    White.bold().underline().paint(kernel),
                    White.bold().paint("..."));
            },
            CliMessage::EnableIpv6(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Enabling IPv6 for droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::EnablePrivateNetworking(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Enabling private networking for droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::SnapshotDroplet(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Taking a snapshot of droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::UpgradeDroplet(id) => {
                print!("{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Upgrading droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::Kernel => {
                print!("{} {}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying kerenl..."));
            },
            CliMessage::DropletAction(id, a_id) => {
                print!("{} {} {} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Displaying action"),
                    White.bold().underline().paint(a_id),
                    White.bold().paint("for droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("..."));
            },
            CliMessage::ResizeDroplet(id, size, disk) => {
                print!("{} {}{}{} {} {}{}",
                    Blue.bold().paint("::"),
                    White.bold().paint("Resizing"),
                    if disk {
                        White.bold().paint(" the disk for ")
                    } else {
                        " "
                    },
                    White.bold().paint("droplet"),
                    White.bold().underline().paint(id),
                    White.bold().paint("to"),
                    White.bold().underline().paint(size),
                    White.bold().paint("..."));
            },
        }
    }

    #[cfg(not(feature="color"))]
    pub fn display(&self) {
        print!("::");
        match *self {
            CliMessage::Account => {
                print!(" Displaying account information...");
            },
            CliMessage::Action => {
                println!(" Displaying account action...\n\t");
            },
            CliMessage::Actions => {
                print!(" Displaying all account actions...\n");
            },
            CliMessage::ActionId(id) => {
                print!(" Displaying account action ID {}...", id);
            },
            CliMessage::Failure => {
                println!("Failed");
            },
            CliMessage::JsonResponse => {
                print!(" Displaying JSON response from DigitalOcean...\n");
            },
            CliMessage::Request(req) => {
                println!(" Displaying sent request...\n\t{}\n", req);
            },
            CliMessage::Success => {
                println!("Success");
            },
            CliMessage::Token(tok) => {
                println!(" Displaying account token...\n\t{}\n", tok);
            },
            CliMessage::Regions => {
                print!(":: Displaying all regions...");
            },
            CliMessage::Sizes => {
                print!("::Displaying all sizes...");
            },
            CliMessage::Images => {
                print!("::Displaying all images...");
            },
            CliMessage::SshKeys => {
                print!(":: Displaying all SSH keys...");
            },
            CliMessage::Dropets => {
                print!(":: Displaying all droplets...");
            },
            CliMessage::Domains => {
                print!(":: Displaying all domains...");
            },
            CliMessage::ImageActions(id) => {
                print!(":: Displaying all actions for image {}...", id);
            },
            CliMessage::Image(id) => {
                print!(":: Displaying image {}...", id);
            },
            CliMessage::UpdateImage(id) => {
                print!(":: Updating image {}...", id);
            },
            CliMessage::DeleteImage(id) => {
                print!(":: Deleting image {}...", id);
            },
            CliMessage::ConvertImage(id) => {
                print!(":: Converting image {}...", id);
            },
            CliMessage::TransferImage(id, region) => {
                print!(":: Transferring image {} to region {}...", id, region);
            },
            CliMessage::ImageAction(id, a_id) => {
                print!(":: Displaying action {} for image {}...", a_id, id);
            }
        }
    }
}<|endoftext|>


<commit_before>use std::cell::{Ref, RefCell, RefMut};
use std::collections::VecDeque;
use std::rc::Rc;

use http::{HeaderMap, Method, StatusCode, Uri, Version};

use crate::extensions::Extensions;

/// Represents various types of connection
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum ConnectionType {
    /// Close connection after response
    Close,
    /// Keep connection alive after response
    KeepAlive,
    /// Connection is upgraded to different type
    Upgrade,
}

#[doc(hidden)]
pub trait Head: Default + 'static {
    fn clear(&mut self);

    /// Connection type
    fn connection_type(&self) -> ConnectionType;

    /// Set connection type of the message
    fn set_connection_type(&mut self, ctype: ConnectionType);

    fn upgrade(&self) -> bool {
        self.connection_type() == ConnectionType::Upgrade
    }

    fn keep_alive(&self) -> bool {
        self.connection_type() == ConnectionType::KeepAlive
    }

    fn pool() -> &'static MessagePool<Self>;
}

#[derive(Debug)]
pub struct RequestHead {
    pub uri: Uri,
    pub method: Method,
    pub version: Version,
    pub headers: HeaderMap,
    pub ctype: Option<ConnectionType>,
}

impl Default for RequestHead {
    fn default() -> RequestHead {
        RequestHead {
            uri: Uri::default(),
            method: Method::default(),
            version: Version::HTTP_11,
            headers: HeaderMap::with_capacity(16),
            ctype: None,
        }
    }
}

impl Head for RequestHead {
    fn clear(&mut self) {
        self.ctype = None;
        self.headers.clear();
    }

    fn set_connection_type(&mut self, ctype: ConnectionType) {
        self.ctype = Some(ctype)
    }

    fn connection_type(&self) -> ConnectionType {
        if let Some(ct) = self.ctype {
            ct
        } else if self.version < Version::HTTP_11 {
            ConnectionType::Close
        } else {
            ConnectionType::KeepAlive
        }
    }

    fn pool() -> &'static MessagePool<Self> {
        REQUEST_POOL.with(|p| *p)
    }
}

#[derive(Debug)]
pub struct ResponseHead {
    pub version: Version,
    pub status: StatusCode,
    pub headers: HeaderMap,
    pub reason: Option<&'static str>,
    pub(crate) ctype: Option<ConnectionType>,
}

impl Default for ResponseHead {
    fn default() -> ResponseHead {
        ResponseHead {
            version: Version::default(),
            status: StatusCode::OK,
            headers: HeaderMap::with_capacity(16),
            reason: None,
            ctype: None,
        }
    }
}

impl Head for ResponseHead {
    fn clear(&mut self) {
        self.ctype = None;
        self.reason = None;
        self.headers.clear();
    }

    fn set_connection_type(&mut self, ctype: ConnectionType) {
        self.ctype = Some(ctype)
    }

    fn connection_type(&self) -> ConnectionType {
        if let Some(ct) = self.ctype {
            ct
        } else if self.version < Version::HTTP_11 {
            ConnectionType::Close
        } else {
            ConnectionType::KeepAlive
        }
    }

    fn pool() -> &'static MessagePool<Self> {
        RESPONSE_POOL.with(|p| *p)
    }
}

impl ResponseHead {
    /// Get custom reason for the response
    #[inline]
    pub fn reason(&self) -> &str {
        if let Some(reason) = self.reason {
            reason
        } else {
            self.status
                .canonical_reason()
                .unwrap_or("<unknown status code>")
        }
    }
}

pub struct Message<T: Head> {
    inner: Rc<MessageInner<T>>,
    pool: &'static MessagePool<T>,
}

impl<T: Head> Message<T> {
    /// Get new message from the pool of objects
    pub fn new() -> Self {
        T::pool().get_message()
    }

    /// Message extensions
    #[inline]
    pub fn extensions(&self) -> Ref<Extensions> {
        self.inner.as_ref().extensions.borrow()
    }

    /// Mutable reference to a the message's extensions
    #[inline]
    pub fn extensions_mut(&self) -> RefMut<Extensions> {
        self.inner.as_ref().extensions.borrow_mut()
    }
}

impl<T: Head> Clone for Message<T> {
    fn clone(&self) -> Self {
        Message {
            inner: self.inner.clone(),
            pool: self.pool,
        }
    }
}

impl<T: Head> std::ops::Deref for Message<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.inner.as_ref().head
    }
}

impl<T: Head> std::ops::DerefMut for Message<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut Rc::get_mut(&mut self.inner)
            .expect("Multiple copies exist")
            .head
    }
}

impl<T: Head> Drop for Message<T> {
    fn drop(&mut self) {
        if Rc::strong_count(&self.inner) == 1 {
            self.pool.release(self.inner.clone());
        }
    }
}

struct MessageInner<T: Head> {
    head: T,
    extensions: RefCell<Extensions>,
}

impl<T: Head> MessageInner<T> {
    #[inline]
    /// Reset request instance
    pub fn reset(&mut self) {
        self.head.clear();
        self.extensions.borrow_mut().clear();
    }
}

impl<T: Head> Default for MessageInner<T> {
    fn default() -> Self {
        MessageInner {
            head: T::default(),
            extensions: RefCell::new(Extensions::new()),
        }
    }
}

#[doc(hidden)]
/// Request's objects pool
pub struct MessagePool<T: Head>(RefCell<VecDeque<Rc<MessageInner<T>>>>);

thread_local!(static REQUEST_POOL: &'static MessagePool<RequestHead> = MessagePool::<RequestHead>::create());
thread_local!(static RESPONSE_POOL: &'static MessagePool<ResponseHead> = MessagePool::<ResponseHead>::create());

impl<T: Head> MessagePool<T> {
    fn create() -> &'static MessagePool<T> {
        let pool = MessagePool(RefCell::new(VecDeque::with_capacity(128)));
        Box::leak(Box::new(pool))
    }

    /// Get message from the pool
    #[inline]
    fn get_message(&'static self) -> Message<T> {
        if let Some(mut msg) = self.0.borrow_mut().pop_front() {
            if let Some(r) = Rc::get_mut(&mut msg) {
                r.reset();
            }
            Message {
                inner: msg,
                pool: self,
            }
        } else {
            Message {
                inner: Rc::new(MessageInner::default()),
                pool: self,
            }
        }
    }

    #[inline]
    /// Release request instance
    fn release(&self, msg: Rc<MessageInner<T>>) {
        let v = &mut self.0.borrow_mut();
        if v.len() < 128 {
            v.push_front(msg);
        }
    }
}
<commit_msg>simplify Message type<commit_after>use std::cell::{Ref, RefCell, RefMut};
use std::collections::VecDeque;
use std::rc::Rc;

use http::{HeaderMap, Method, StatusCode, Uri, Version};

use crate::extensions::Extensions;

/// Represents various types of connection
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum ConnectionType {
    /// Close connection after response
    Close,
    /// Keep connection alive after response
    KeepAlive,
    /// Connection is upgraded to different type
    Upgrade,
}

#[doc(hidden)]
pub trait Head: Default + 'static {
    fn clear(&mut self);

    /// Connection type
    fn connection_type(&self) -> ConnectionType;

    /// Set connection type of the message
    fn set_connection_type(&mut self, ctype: ConnectionType);

    fn upgrade(&self) -> bool {
        self.connection_type() == ConnectionType::Upgrade
    }

    fn keep_alive(&self) -> bool {
        self.connection_type() == ConnectionType::KeepAlive
    }

    fn pool() -> &'static MessagePool<Self>;
}

#[derive(Debug)]
pub struct RequestHead {
    pub uri: Uri,
    pub method: Method,
    pub version: Version,
    pub headers: HeaderMap,
    pub ctype: Option<ConnectionType>,
    pub extensions: RefCell<Extensions>,
}

impl Default for RequestHead {
    fn default() -> RequestHead {
        RequestHead {
            uri: Uri::default(),
            method: Method::default(),
            version: Version::HTTP_11,
            headers: HeaderMap::with_capacity(16),
            ctype: None,
            extensions: RefCell::new(Extensions::new()),
        }
    }
}

impl Head for RequestHead {
    fn clear(&mut self) {
        self.ctype = None;
        self.headers.clear();
        self.extensions.borrow_mut().clear();
    }

    fn set_connection_type(&mut self, ctype: ConnectionType) {
        self.ctype = Some(ctype)
    }

    fn connection_type(&self) -> ConnectionType {
        if let Some(ct) = self.ctype {
            ct
        } else if self.version < Version::HTTP_11 {
            ConnectionType::Close
        } else {
            ConnectionType::KeepAlive
        }
    }

    fn pool() -> &'static MessagePool<Self> {
        REQUEST_POOL.with(|p| *p)
    }
}

impl RequestHead {
    /// Message extensions
    #[inline]
    pub fn extensions(&self) -> Ref<Extensions> {
        self.extensions.borrow()
    }

    /// Mutable reference to a the message's extensions
    #[inline]
    pub fn extensions_mut(&self) -> RefMut<Extensions> {
        self.extensions.borrow_mut()
    }
}

#[derive(Debug)]
pub struct ResponseHead {
    pub version: Version,
    pub status: StatusCode,
    pub headers: HeaderMap,
    pub reason: Option<&'static str>,
    pub(crate) ctype: Option<ConnectionType>,
}

impl Default for ResponseHead {
    fn default() -> ResponseHead {
        ResponseHead {
            version: Version::default(),
            status: StatusCode::OK,
            headers: HeaderMap::with_capacity(16),
            reason: None,
            ctype: None,
        }
    }
}

impl Head for ResponseHead {
    fn clear(&mut self) {
        self.ctype = None;
        self.reason = None;
        self.headers.clear();
    }

    fn set_connection_type(&mut self, ctype: ConnectionType) {
        self.ctype = Some(ctype)
    }

    fn connection_type(&self) -> ConnectionType {
        if let Some(ct) = self.ctype {
            ct
        } else if self.version < Version::HTTP_11 {
            ConnectionType::Close
        } else {
            ConnectionType::KeepAlive
        }
    }

    fn pool() -> &'static MessagePool<Self> {
        RESPONSE_POOL.with(|p| *p)
    }
}

impl ResponseHead {
    /// Get custom reason for the response
    #[inline]
    pub fn reason(&self) -> &str {
        if let Some(reason) = self.reason {
            reason
        } else {
            self.status
                .canonical_reason()
                .unwrap_or("<unknown status code>")
        }
    }
}

pub struct Message<T: Head> {
    head: Rc<T>,
    pool: &'static MessagePool<T>,
}

impl<T: Head> Message<T> {
    /// Get new message from the pool of objects
    pub fn new() -> Self {
        T::pool().get_message()
    }
}

impl<T: Head> Clone for Message<T> {
    fn clone(&self) -> Self {
        Message {
            head: self.head.clone(),
            pool: self.pool,
        }
    }
}

impl<T: Head> std::ops::Deref for Message<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.head.as_ref()
    }
}

impl<T: Head> std::ops::DerefMut for Message<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        Rc::get_mut(&mut self.head).expect("Multiple copies exist")
    }
}

impl<T: Head> Drop for Message<T> {
    fn drop(&mut self) {
        if Rc::strong_count(&self.head) == 1 {
            self.pool.release(self.head.clone());
        }
    }
}

#[doc(hidden)]
/// Request's objects pool
pub struct MessagePool<T: Head>(RefCell<VecDeque<Rc<T>>>);

thread_local!(static REQUEST_POOL: &'static MessagePool<RequestHead> = MessagePool::<RequestHead>::create());
thread_local!(static RESPONSE_POOL: &'static MessagePool<ResponseHead> = MessagePool::<ResponseHead>::create());

impl<T: Head> MessagePool<T> {
    fn create() -> &'static MessagePool<T> {
        let pool = MessagePool(RefCell::new(VecDeque::with_capacity(128)));
        Box::leak(Box::new(pool))
    }

    /// Get message from the pool
    #[inline]
    fn get_message(&'static self) -> Message<T> {
        if let Some(mut msg) = self.0.borrow_mut().pop_front() {
            if let Some(r) = Rc::get_mut(&mut msg) {
                r.clear();
            }
            Message {
                head: msg,
                pool: self,
            }
        } else {
            Message {
                head: Rc::new(T::default()),
                pool: self,
            }
        }
    }

    #[inline]
    /// Release request instance
    fn release(&self, msg: Rc<T>) {
        let v = &mut self.0.borrow_mut();
        if v.len() < 128 {
            v.push_front(msg);
        }
    }
}
<|endoftext|>


<commit_before>//! Implements the rules of chess and static position evaluation
//! logic.

#![allow(dead_code)]
#![allow(unused_variables)]

pub mod board_geometry;
pub mod board;

// use notation;
use basetypes::*;
use chess_move::*;
use self::board::{Board, IllegalBoard};

pub type Value = i16;

/// Represents an illegal possiton error.
pub struct IllegalPosition;

/// Represents a chess position.
///
/// `Position` can generate all possible moves in the current
/// position, play a selected move, and take it back. It can also
/// statically (without doing extensive tree-searching) evaluate the
/// chances of the sides, so that tree-searching algorithms can use
/// this evaluation to assign realistic game outcomes to their leaf
/// nodes. `Position` can also fabricate a "null move" that can be
/// used to aggressively prune the search tree.
pub struct Position {
    board: Board,
    halfmove_clock: u32,
    fullmove_number: u32, /* move_stack
                           * move_history (including fullmove_number?)
                           * ply
                           * hply?
                           * various hash tables
                           * first_move_index[usize; MAX_PLY]
                           * undo_move data stack */
}

impl Position {
    fn from_fen(fen: &str) -> Result<Position, IllegalBoard> {
        let parts: Vec<_> = fen.split_whitespace().collect();

        if parts.len() == 6 {
            let p = Position {
                board: try!(Board::from_fen(fen)),
                halfmove_clock: try!(parts[4].parse::<u32>().map_err(|_| IllegalBoard)),
                fullmove_number: try!(parts[5].parse::<u32>().map_err(|_| IllegalBoard)),
            };
            Ok(p)
        } else {
            Err(IllegalBoard)
        }
    }

    /// Creates a new instance.
    ///
    /// `fen` should be the Forsyth–Edwards Notation of a legal
    /// starting position. `moves` should be an iterator over all the
    /// moves that were played from that position.
    pub fn from_history(fen: &str,
                        moves: &mut Iterator<Item = &str>)
                        -> Result<Position, IllegalPosition> {
        Err(IllegalPosition)
    }

    /// Evaluates a final position.
    ///
    /// In final positions this method is guaranteed to return the
    /// correct value of the position (white wins, black wins,
    /// draw). A position is guaranteed to be final if
    /// `generate_moves` method generates no legal moves (it may
    /// generate some pseudo-legal moves, but if none of them is
    /// legal, then the position is guaranteed to be a final
    /// position).
    pub fn evaluate_final(&self) -> Value {
        0
    }

    /// Statically evaluates the position.
    ///
    /// This method considers only static material and positional
    /// properties of the position. If the position is dynamic, with
    /// pending tactical threats, this function will return a grossly
    /// incorrect evaluation. Therefore, if should be relied upon only
    /// for reasonably "quiet" positions.
    pub fn evaluate_static(&self) -> Value {
        0
    }

    /// Performs "quiescence search" and returns an evaluation.
    ///
    /// The purpose of the "quiescence search" is to only evaluate
    /// "quiet" positions (positions where there are no winning
    /// tactical moves to be made).
    ///
    /// TODO: Add more details for the algorithm used.
    pub fn evaluate(&self) -> Value {
        0
    }

    /// Returns an almost unique hash value for the position.
    #[inline(always)]
    pub fn hash(&self) -> u64 {
        0
    }

    /// Plays a move on the board.
    ///
    /// It verifies if the move is legal. If the move is legal, the
    /// board is updated and `true` is returned. If the move is
    /// illegal, `false` is returned without updating the board. The
    /// move passed to this method **must** have been generated by
    /// `generate_moves` or `null_move` methods for the current
    /// position on the board.
    ///
    /// Moves generated by the `null_move` method are exceptions. For
    /// them `do_move(m)` will return `false` if and only if the king
    /// is in check.
    #[inline]
    pub fn do_move(&self, m: Move) -> bool {
        false
    }

    /// Takes back the last played move.
    #[inline]
    pub fn undo_move(&self) {}

    /// Generates pseudo-legal moves and write them to `move_stack`.
    ///
    /// If all of the moves generated by this methods are illegal
    /// (this means that `do_move(m)` returns `false` for all of
    /// them), then it is guaranteed that the position is final, and
    /// `evaluate_final()` will return its correct value.
    #[inline]
    pub fn generate_moves(&self, move_stack: &mut Vec<Move>) {}

    /// Returns a null move.
    ///
    /// "Null move" is an illegal pseudo-move that changes only the
    /// side to move. For the move generated by this method,
    /// `do_move(m)` will return `false` if and only if the king is in
    /// check.
    #[inline]
    pub fn null_move(&self) -> Move {
        use castling_rights::CastlingRights;
        Move::new(WHITE,
                  0,
                  MOVE_NORMAL,
                  KING,
                  0,
                  0,
                  NO_PIECE,
                  8, // no en-passant file
                  CastlingRights::new(),
                  0)
    }
}

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

    #[test]
    fn test_fen_parsing() {
        assert!(Position::from_fen("nbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr1/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBN b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR/ b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNRR b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPP01PPP/RNBQKBNR b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPP91PPP/RNBQKBNR b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPP*1PPP/RNBQKBNR b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 * 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 *")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b - e3 0 1")
                    .is_ok());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1")
                    .is_ok());
        assert!(Position::from_fen("8/8/8/8/8/8/8/8 w - - 0 1").is_err());
        assert!(Position::from_fen("8/8/8/8/8/8/8/7K w - - 0 1").is_err());
        assert!(Position::from_fen("k7/8/8/8/8/8/8/7K w - - 0 1").is_ok());
        assert!(Position::from_fen("k7/8/8/8/8/8/8/6KK w - - 0 1").is_err());
        assert!(Position::from_fen("k7/pppppppp/p7/8/8/8/8/7K w - - 0 1").is_err());
        assert!(Position::from_fen("k7/8/8/8/8/7P/PPPPPPPP/7K w - - 0 1").is_err());
        assert!(Position::from_fen("k7/pppppppp/8/8/8/8/PPPPPPPP/7K w - - 0 1").is_ok());
        assert!(Position::from_fen("k7/1P6/8/8/8/8/8/7K w - - 0 1").is_err());
        assert!(Position::from_fen("k7/1B6/8/8/8/8/8/7K w - - 0 1").is_err());
        assert!(Position::from_fen("k7/1N6/8/8/8/8/8/7K w - - 0 1").is_ok());
        assert!(Position::from_fen("k3P3/8/8/8/8/8/8/7K w - - 0 1").is_err());
        assert!(Position::from_fen("k3p3/8/8/8/8/8/8/7K w - - 0 1").is_err());
        assert!(Position::from_fen("k7/8/8/8/8/8/8/pP5K w - - 0 1").is_err());
        assert!(Position::from_fen("r3k2r/8/8/8/8/8/8/R3K2R w KQkq - 0 1").is_ok());
        assert!(Position::from_fen("r3k2r/8/8/8/8/8/8/R3K2B w KQkq - 0 1").is_err());
        assert!(Position::from_fen("r3k2r/8/8/8/8/8/8/R3K3 w KQkq - 0 1").is_err());
        assert!(Position::from_fen("r3k2r/8/8/8/8/8/8/R3K3 w KQkq - 0 1").is_err());
        assert!(Position::from_fen("r3k2r/8/8/8/8/8/8/R3K3 w Qkq - 0 1").is_ok());
        assert!(Position::from_fen("r2k3r/8/8/8/8/8/8/R3K3 w Qkq - 0 1").is_err());
        assert!(Position::from_fen("r2k3r/8/8/8/8/8/8/R3K3 w Qk - 0 1").is_err());
        assert!(Position::from_fen("r2k3r/8/8/8/8/8/8/R3K3 w Q - 0 1").is_ok());
        assert!(Position::from_fen("k7/8/8/8/7P/8/8/7K w - h3 0 1").is_err());
        assert!(Position::from_fen("k7/8/8/8/7P/8/8/7K b - h3 0 1").is_ok());
        assert!(Position::from_fen("k7/8/8/7P/8/8/8/7K b - h4 0 1").is_err());
        assert!(Position::from_fen("k7/8/8/8/7P/7P/8/7K b - h3 0 1").is_err());
        assert!(Position::from_fen("k7/8/8/8/7P/8/7P/7K b - h3 0 1").is_err());
        assert!(Position::from_fen("k7/8/8/8/6P1/7P/8/7K b - h3 0 1").is_err());
        assert!(Position::from_fen("8/8/8/6k1/7P/8/8/7K b - h3 0 1").is_ok());
        assert!(Position::from_fen("8/8/8/6k1/7P/8/8/6RK b - h3 0 1").is_err());
        assert!(Position::from_fen("8/8/8/6k1/3P4/8/8/2B4K b - d3 0 1").is_ok());
        assert!(Position::from_fen("8/8/8/6k1/7P/4B3/8/7K b - h3 0 1").is_err());
    }
}
<commit_msg>added docs<commit_after>//! Implements the rules of chess and static position evaluation
//! logic.

#![allow(dead_code)]
#![allow(unused_variables)]

pub mod board_geometry;
pub mod board;

// use notation;
use basetypes::*;
use chess_move::*;
use self::board::{Board, IllegalBoard};

pub type Value = i16;

/// Represents an illegal possiton error.
pub struct IllegalPosition;

/// Represents a chess position.
///
/// `Position` can generate all possible moves in the current
/// position, play a selected move, and take it back. It can also
/// statically (without doing extensive tree-searching) evaluate the
/// chances of the sides, so that tree-searching algorithms can use
/// this evaluation to assign realistic game outcomes to their leaf
/// nodes. `Position` can also fabricate a "null move" that can be
/// used to aggressively prune the search tree.
pub struct Position {
    board: Board,
    halfmove_clock: u32,
    fullmove_number: u32, /* move_stack
                           * move_history (including fullmove_number?)
                           * ply
                           * hply?
                           * various hash tables
                           * first_move_index[usize; MAX_PLY]
                           * undo_move data stack */
}

impl Position {
    fn from_fen(fen: &str) -> Result<Position, IllegalBoard> {
        let parts: Vec<_> = fen.split_whitespace().collect();

        if parts.len() == 6 {
            let p = Position {
                board: try!(Board::from_fen(fen)),
                halfmove_clock: try!(parts[4].parse::<u32>().map_err(|_| IllegalBoard)),
                fullmove_number: try!(parts[5].parse::<u32>().map_err(|_| IllegalBoard)),
            };
            Ok(p)
        } else {
            Err(IllegalBoard)
        }
    }

    /// Creates a new instance.
    ///
    /// `fen` should be the Forsyth–Edwards Notation of a legal
    /// starting position. `moves` should be an iterator over all the
    /// moves that were played from that position.
    pub fn from_history(fen: &str,
                        moves: &mut Iterator<Item = &str>)
                        -> Result<Position, IllegalPosition> {
        Err(IllegalPosition)
    }

    /// Evaluates a final position.
    ///
    /// In final positions this method is guaranteed to return the
    /// correct value of the position (white wins, black wins,
    /// draw). A position is guaranteed to be final if
    /// `generate_moves` method generates no legal moves (it may
    /// generate some pseudo-legal moves, but if none of them is
    /// legal, then the position is guaranteed to be a final
    /// position).
    pub fn evaluate_final(&self) -> Value {
        0
    }

    /// Statically evaluates the position.
    ///
    /// This method considers only static material and positional
    /// properties of the position. If the position is dynamic, with
    /// pending tactical threats, this function will return a grossly
    /// incorrect evaluation. Therefore, if should be relied upon only
    /// for reasonably "quiet" positions.
    ///
    /// `lower_bound` and `upper_bound` together give the interval
    /// within which an as precise as possible evaluation is
    /// required. If during the calculation it is determined that the
    /// evaluation is outside this interval, this method may return
    /// any value outside of the interval (including the bounds), but
    /// always staying on the correct side of the interval.
    pub fn evaluate_static(&self, lower_bound: Value, upper_bound: Value) -> Value {
        0
    }

    /// Performs "quiescence search" and returns an evaluation.
    ///
    /// The purpose of the "quiescence search" is to only evaluate
    /// "quiet" positions (positions where there are no winning
    /// tactical moves to be made).
    ///
    /// `lower_bound` and `upper_bound` together give the interval
    /// within which an as precise as possible evaluation is
    /// required. If during the calculation it is determined that the
    /// evaluation is outside this interval, this method may return
    /// any value outside of the interval (including the bounds), but
    /// always staying on the correct side of the interval.
    ///
    /// TODO: Add more details for the algorithm used.
    pub fn evaluate(&self, lower_bound: Value, upper_bound: Value) -> Value {
        0
    }

    /// Returns an almost unique hash value for the position.
    #[inline(always)]
    pub fn hash(&self) -> u64 {
        0
    }

    /// Plays a move on the board.
    ///
    /// It verifies if the move is legal. If the move is legal, the
    /// board is updated and `true` is returned. If the move is
    /// illegal, `false` is returned without updating the board. The
    /// move passed to this method **must** have been generated by
    /// `generate_moves` or `null_move` methods for the current
    /// position on the board.
    ///
    /// Moves generated by the `null_move` method are exceptions. For
    /// them `do_move(m)` will return `false` if and only if the king
    /// is in check.
    #[inline]
    pub fn do_move(&self, m: Move) -> bool {
        false
    }

    /// Takes back the last played move.
    #[inline]
    pub fn undo_move(&self) {}

    /// Generates pseudo-legal moves and write them to `move_stack`.
    ///
    /// If all of the moves generated by this methods are illegal
    /// (this means that `do_move(m)` returns `false` for all of
    /// them), then it is guaranteed that the position is final, and
    /// `evaluate_final()` will return its correct value.
    #[inline]
    pub fn generate_moves(&self, move_stack: &mut Vec<Move>) {}

    /// Returns a null move.
    ///
    /// "Null move" is an illegal pseudo-move that changes only the
    /// side to move. For the move generated by this method,
    /// `do_move(m)` will return `false` if and only if the king is in
    /// check.
    #[inline]
    pub fn null_move(&self) -> Move {
        use castling_rights::CastlingRights;
        Move::new(WHITE,
                  0,
                  MOVE_NORMAL,
                  KING,
                  0,
                  0,
                  NO_PIECE,
                  8, // no en-passant file
                  CastlingRights::new(),
                  0)
    }
}

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

    #[test]
    fn test_fen_parsing() {
        assert!(Position::from_fen("nbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr1/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBN b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR/ b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNRR b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPP01PPP/RNBQKBNR b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPP91PPP/RNBQKBNR b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPP*1PPP/RNBQKBNR b KQkq e3 0 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 * 1")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 *")
                    .is_err());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b - e3 0 1")
                    .is_ok());
        assert!(Position::from_fen("rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1")
                    .is_ok());
        assert!(Position::from_fen("8/8/8/8/8/8/8/8 w - - 0 1").is_err());
        assert!(Position::from_fen("8/8/8/8/8/8/8/7K w - - 0 1").is_err());
        assert!(Position::from_fen("k7/8/8/8/8/8/8/7K w - - 0 1").is_ok());
        assert!(Position::from_fen("k7/8/8/8/8/8/8/6KK w - - 0 1").is_err());
        assert!(Position::from_fen("k7/pppppppp/p7/8/8/8/8/7K w - - 0 1").is_err());
        assert!(Position::from_fen("k7/8/8/8/8/7P/PPPPPPPP/7K w - - 0 1").is_err());
        assert!(Position::from_fen("k7/pppppppp/8/8/8/8/PPPPPPPP/7K w - - 0 1").is_ok());
        assert!(Position::from_fen("k7/1P6/8/8/8/8/8/7K w - - 0 1").is_err());
        assert!(Position::from_fen("k7/1B6/8/8/8/8/8/7K w - - 0 1").is_err());
        assert!(Position::from_fen("k7/1N6/8/8/8/8/8/7K w - - 0 1").is_ok());
        assert!(Position::from_fen("k3P3/8/8/8/8/8/8/7K w - - 0 1").is_err());
        assert!(Position::from_fen("k3p3/8/8/8/8/8/8/7K w - - 0 1").is_err());
        assert!(Position::from_fen("k7/8/8/8/8/8/8/pP5K w - - 0 1").is_err());
        assert!(Position::from_fen("r3k2r/8/8/8/8/8/8/R3K2R w KQkq - 0 1").is_ok());
        assert!(Position::from_fen("r3k2r/8/8/8/8/8/8/R3K2B w KQkq - 0 1").is_err());
        assert!(Position::from_fen("r3k2r/8/8/8/8/8/8/R3K3 w KQkq - 0 1").is_err());
        assert!(Position::from_fen("r3k2r/8/8/8/8/8/8/R3K3 w KQkq - 0 1").is_err());
        assert!(Position::from_fen("r3k2r/8/8/8/8/8/8/R3K3 w Qkq - 0 1").is_ok());
        assert!(Position::from_fen("r2k3r/8/8/8/8/8/8/R3K3 w Qkq - 0 1").is_err());
        assert!(Position::from_fen("r2k3r/8/8/8/8/8/8/R3K3 w Qk - 0 1").is_err());
        assert!(Position::from_fen("r2k3r/8/8/8/8/8/8/R3K3 w Q - 0 1").is_ok());
        assert!(Position::from_fen("k7/8/8/8/7P/8/8/7K w - h3 0 1").is_err());
        assert!(Position::from_fen("k7/8/8/8/7P/8/8/7K b - h3 0 1").is_ok());
        assert!(Position::from_fen("k7/8/8/7P/8/8/8/7K b - h4 0 1").is_err());
        assert!(Position::from_fen("k7/8/8/8/7P/7P/8/7K b - h3 0 1").is_err());
        assert!(Position::from_fen("k7/8/8/8/7P/8/7P/7K b - h3 0 1").is_err());
        assert!(Position::from_fen("k7/8/8/8/6P1/7P/8/7K b - h3 0 1").is_err());
        assert!(Position::from_fen("8/8/8/6k1/7P/8/8/7K b - h3 0 1").is_ok());
        assert!(Position::from_fen("8/8/8/6k1/7P/8/8/6RK b - h3 0 1").is_err());
        assert!(Position::from_fen("8/8/8/6k1/3P4/8/8/2B4K b - d3 0 1").is_ok());
        assert!(Position::from_fen("8/8/8/6k1/7P/4B3/8/7K b - h3 0 1").is_err());
    }
}
<|endoftext|>


<commit_before>mod testdata;
use testdata::{
    newton,
    generate_data,
    NEWTON_ITER,
    SETLEN
};

use std::time::SystemTime;
use std::thread;
use std::thread::JoinHandle;
use std::iter::Map;
use std::slice::Chunks;
use std::sync::Arc;
use std::boxed::Box;
use std::sync::Mutex;

const THREADS: usize = 4;

fn main() {
    let data = generate_data(SETLEN);
    println!("generiere {} testdaten", SETLEN);
    let earlier = SystemTime::now();
    let _ = map_data(data);
    let dur = match SystemTime::now().duration_since(earlier) {
        Ok(v) => v,
        Err(e) => {
            println!("messfehler: {}", e);
            return;
        }
    };
    println!("duration: {}.{} secs", dur.as_secs(), dur.subsec_nanos());
}

fn map_data(data: Vec<f64>) -> Vec<f64> {
    let mut handles:Vec<JoinHandle<Vec<f64>>> = Vec::new();
    let mut data = data.chunks(data.len()/THREADS + 1).
                                        map(|x| Arc::new(x.to_owned()));
    println!("{}", data.len());
    for d in data {
        handles.push(thread::spawn(move || d.iter().map(|x| newton(*x, NEWTON_ITER)).collect()));
    }
    handles.into_iter().flat_map(|x| x.join().unwrap()).collect()
}
<commit_msg>Remove println in pmap2<commit_after>mod testdata;
use testdata::{
    newton,
    generate_data,
    NEWTON_ITER,
    SETLEN
};

use std::time::SystemTime;
use std::thread;
use std::thread::JoinHandle;
use std::iter::Map;
use std::slice::Chunks;
use std::sync::Arc;
use std::boxed::Box;
use std::sync::Mutex;

const THREADS: usize = 4;

fn main() {
    let data = generate_data(SETLEN);
    println!("generiere {} testdaten", SETLEN);
    let earlier = SystemTime::now();
    let _ = map_data(data);
    let dur = match SystemTime::now().duration_since(earlier) {
        Ok(v) => v,
        Err(e) => {
            println!("messfehler: {}", e);
            return;
        }
    };
    println!("duration: {}.{} secs", dur.as_secs(), dur.subsec_nanos());
}

fn map_data(data: Vec<f64>) -> Vec<f64> {
    let mut handles:Vec<JoinHandle<Vec<f64>>> = Vec::new();
    let mut data = data.chunks(data.len()/THREADS + 1).
                                        map(|x| Arc::new(x.to_owned()));
    for d in data {
        handles.push(thread::spawn(move || d.iter().map(|x| newton(*x, NEWTON_ITER)).collect()));
    }
    handles.into_iter().flat_map(|x| x.join().unwrap()).collect()
}
<|endoftext|>