<commit_before>
use std::str::Utf8Error;
use std::string::FromUtf8Error;
use std::convert::From;
use std::io::Error as IoError;
use std::error::Error as StdError;
use std::fmt;

/// A trait for Errors produced by the consumer of this library
pub trait UserError: StdError { }

/// These are errors returned to the caller
#[derive(Debug)]
pub enum OAuthError<E: UserError> {
    Utf8Error(Utf8Error),
    FromUtf8Error(FromUtf8Error),
    Url(::url::ParseError),
    Io(IoError),
    AuthzBadRequest,
    AuthzMissingClientId,
    AuthzUnknownClient,
    AuthzRedirectUrlNotRegistered,
    AuthzGrantTypeMissing,
    AuthzClientIdMismatch,
    ClientCodeMissing,
    ClientStateMissing,
    ClientNonceMismatch,
    UnexpectedStatusCode,
    UserError(E),
}

impl<E: UserError> fmt::Display for OAuthError<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        match *self {
            OAuthError::Utf8Error(ref e) => e.fmt(f),
            OAuthError::FromUtf8Error(ref e) => e.fmt(f),
            OAuthError::Url(ref e) => e.fmt(f),
            OAuthError::Io(ref e) => e.fmt(f),
            OAuthError::UserError(ref e) => fmt::Display::fmt(e,f),
            ref e => write!(f, "{}", e.description()),
        }
    }
}

impl<E: UserError> StdError for OAuthError<E> {
    fn description(&self) -> &str {
        match *self {
            OAuthError::Utf8Error(ref e) => e.description(),
            OAuthError::FromUtf8Error(ref e) => e.description(),
            OAuthError::Url(ref e) => e.description(),
            OAuthError::Io(ref e) => e.description(),
            OAuthError::AuthzBadRequest => "Bad Request",
            OAuthError::AuthzMissingClientId => "Missing `client_id`",
            OAuthError::AuthzUnknownClient => "Unknown Client",
            OAuthError::AuthzRedirectUrlNotRegistered => "`redirect_url` Not Registered",
            OAuthError::AuthzGrantTypeMissing => "`grant_type` Missing",
            OAuthError::AuthzClientIdMismatch => "`client_id` mismatch",
            OAuthError::ClientCodeMissing => "`code` Missing",
            OAuthError::ClientStateMissing => "`state` Missing",
            OAuthError::ClientNonceMismatch => "`nonce` Mismatch",
            OAuthError::UnexpectedStatusCode => "Unexpected HTTP Status Code",
            OAuthError::UserError(ref e) => e.description(),
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            OAuthError::Utf8Error(ref e) => Some(e),
            OAuthError::FromUtf8Error(ref e) => Some(e),
            OAuthError::Url(ref e) => Some(e),
            OAuthError::Io(ref e) => Some(e),
            OAuthError::UserError(ref e) => Some(e),
            _ => None,
        }
    }
}

impl<E: UserError> From<Utf8Error> for OAuthError<E> {
    fn from(e: Utf8Error) -> OAuthError<E> {
        OAuthError::Utf8Error(e)
    }
}

impl<E: UserError> From<FromUtf8Error> for OAuthError<E> {
    fn from(e: FromUtf8Error) -> OAuthError<E> {
        OAuthError::FromUtf8Error(e)
    }
}

impl<E: UserError> From<::url::ParseError> for OAuthError<E> {
    fn from(e: ::url::ParseError) -> OAuthError<E> {
        OAuthError::Url(e)
    }
}

impl<E: UserError> From<IoError> for OAuthError<E> {
    fn from(e: IoError) -> OAuthError<E> {
        OAuthError::Io(e)
    }
}

impl<E: UserError> From<E> for OAuthError<E> {
    fn from(e: E) -> OAuthError<E> {
        OAuthError::UserError(e)
    }
}
<commit_msg>OAuthError::ParseInt<commit_after>
use std::str::Utf8Error;
use std::string::FromUtf8Error;
use std::convert::From;
use std::io::Error as IoError;
use std::num::ParseIntError;
use std::error::Error as StdError;
use std::fmt;

/// A trait for Errors produced by the consumer of this library
pub trait UserError: StdError { }

/// These are errors returned to the caller
#[derive(Debug)]
pub enum OAuthError<E: UserError> {
    Utf8Error(Utf8Error),
    FromUtf8Error(FromUtf8Error),
    Url(::url::ParseError),
    Io(IoError),
    ParseInt(ParseIntError),
    AuthzBadRequest,
    AuthzMissingClientId,
    AuthzUnknownClient,
    AuthzRedirectUrlNotRegistered,
    AuthzGrantTypeMissing,
    AuthzClientIdMismatch,
    AuthzGrantNotFound,
    ClientCodeMissing,
    ClientStateMissing,
    ClientNonceMismatch,
    UnexpectedStatusCode,
    UserError(E),
}

impl<E: UserError> fmt::Display for OAuthError<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        match *self {
            OAuthError::Utf8Error(ref e) => e.fmt(f),
            OAuthError::FromUtf8Error(ref e) => e.fmt(f),
            OAuthError::Url(ref e) => e.fmt(f),
            OAuthError::Io(ref e) => e.fmt(f),
            OAuthError::ParseInt(ref e) => e.fmt(f),
            OAuthError::UserError(ref e) => fmt::Display::fmt(e,f),
            ref e => write!(f, "{}", e.description()),
        }
    }
}

impl<E: UserError> StdError for OAuthError<E> {
    fn description(&self) -> &str {
        match *self {
            OAuthError::Utf8Error(ref e) => e.description(),
            OAuthError::FromUtf8Error(ref e) => e.description(),
            OAuthError::Url(ref e) => e.description(),
            OAuthError::Io(ref e) => e.description(),
            OAuthError::ParseInt(ref e) => e.description(),
            OAuthError::AuthzBadRequest => "Bad Request",
            OAuthError::AuthzMissingClientId => "Missing `client_id`",
            OAuthError::AuthzUnknownClient => "Unknown Client",
            OAuthError::AuthzRedirectUrlNotRegistered => "`redirect_url` Not Registered",
            OAuthError::AuthzGrantTypeMissing => "`grant_type` Missing",
            OAuthError::AuthzClientIdMismatch => "`client_id` mismatch",
            OAuthError::AuthzGrantNotFound => "grant not found",
            OAuthError::ClientCodeMissing => "`code` Missing",
            OAuthError::ClientStateMissing => "`state` Missing",
            OAuthError::ClientNonceMismatch => "`nonce` Mismatch",
            OAuthError::UnexpectedStatusCode => "Unexpected HTTP Status Code",
            OAuthError::UserError(ref e) => e.description(),
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            OAuthError::Utf8Error(ref e) => Some(e),
            OAuthError::FromUtf8Error(ref e) => Some(e),
            OAuthError::Url(ref e) => Some(e),
            OAuthError::Io(ref e) => Some(e),
            OAuthError::ParseInt(ref e) => Some(e),
            OAuthError::UserError(ref e) => Some(e),
            _ => None,
        }
    }
}

impl<E: UserError> From<Utf8Error> for OAuthError<E> {
    fn from(e: Utf8Error) -> OAuthError<E> {
        OAuthError::Utf8Error(e)
    }
}

impl<E: UserError> From<FromUtf8Error> for OAuthError<E> {
    fn from(e: FromUtf8Error) -> OAuthError<E> {
        OAuthError::FromUtf8Error(e)
    }
}

impl<E: UserError> From<::url::ParseError> for OAuthError<E> {
    fn from(e: ::url::ParseError) -> OAuthError<E> {
        OAuthError::Url(e)
    }
}

impl<E: UserError> From<IoError> for OAuthError<E> {
    fn from(e: IoError) -> OAuthError<E> {
        OAuthError::Io(e)
    }
}

impl<E: UserError> From<ParseIntError> for OAuthError<E> {
    fn from(e: ParseIntError) -> OAuthError<E> {
        OAuthError::ParseInt(e)
    }
}

impl<E: UserError> From<E> for OAuthError<E> {
    fn from(e: E) -> OAuthError<E> {
        OAuthError::UserError(e)
    }
}
<|endoftext|>


<commit_before>use std::num::ParseIntError;
use std::net::AddrParseError;
use std::fmt;
use std::error;
use std::error::Error;

#[derive(Debug)]
pub enum SdpParserError {
    Line { message: String, line: String },
    Unsupported { message: String, line: String },
    Sequence {
        message: String,
        line: Option<usize>,
    },
    Integer(ParseIntError),
    Address(AddrParseError),
}

impl fmt::Display for SdpParserError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SdpParserError::Line {
                ref message,
                ref line,
            } => write!(f, "Line error: {} in line: {}", message, line),
            SdpParserError::Unsupported {
                ref message,
                ref line,
            } => write!(f, "Unsupported: {} in line: {}", message, line),
            SdpParserError::Sequence { ref message, .. } => {
                write!(f, "Sequence error: {}", message)
            }
            SdpParserError::Integer(ref err) => {
                write!(f, "Integer parsing error: {}", err.description())
            }
            SdpParserError::Address(ref err) => {
                write!(f, "IP address parsing error: {}", err.description())
            }
        }
    }
}

impl error::Error for SdpParserError {
    fn description(&self) -> &str {
        match *self {
            SdpParserError::Line { ref message, .. } |
            SdpParserError::Unsupported { ref message, .. } |
            SdpParserError::Sequence { ref message, .. } => message,
            SdpParserError::Integer(ref err) => err.description(),
            SdpParserError::Address(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            SdpParserError::Integer(ref err) => Some(err),
            SdpParserError::Address(ref err) => Some(err),
            // Can't tell much more about our internal errors
            _ => None,
        }
    }
}

impl From<ParseIntError> for SdpParserError {
    fn from(err: ParseIntError) -> SdpParserError {
        SdpParserError::Integer(err)
    }
}

impl From<AddrParseError> for SdpParserError {
    fn from(err: AddrParseError) -> SdpParserError {
        SdpParserError::Address(err)
    }
}

#[test]
fn test_sdp_parser_error_line() {
    let line = SdpParserError::Line {
        message: "test message".to_string(),
        line: "test line".to_string(),
    };
    // TODO how to verify the output of fmt::Display() ?
    println!("{}", line);
    assert_eq!(line.description(), "test message");
    assert!(line.cause().is_none());
}

#[test]
fn test_sdp_parser_error_unsupported() {
    let unsupported = SdpParserError::Unsupported {
        message: "unsupported message".to_string(),
        line: "unsupported line".to_string(),
    };
    // TODO how to verify the output of fmt::Display() ?
    println!("{}", unsupported);
    assert_eq!(unsupported.description(), "unsupported message");
    assert!(unsupported.cause().is_none());
}

#[test]
fn test_sdp_parser_error_sequence() {
    let sequence1 = SdpParserError::Sequence {
        message: "sequence message".to_string(),
        line: None,
    };
    // TODO how to verify the output of fmt::Display() ?
    println!("{}", sequence1);
    assert_eq!(sequence1.description(), "sequence message");
    assert!(sequence1.cause().is_none());

    let sequence2 = SdpParserError::Sequence {
        message: "another sequence message".to_string(),
        line: Some(5),
    };
    // TODO how to verify the output of fmt::Display() ?
    println!("{}", sequence2);
    assert_eq!(sequence2.description(), "another sequence message");
    assert!(sequence2.cause().is_none());
}

#[test]
fn test_sdp_parser_error_integer() {
    let v = "12a";
    let integer = v.parse::<u64>();
    assert!(integer.is_err());
    // TODO how to verify the output of fmt::Display() ?
    let int_err = integer.err().unwrap();
    println!("{}", int_err);
    println!("{}", int_err.description());
    assert!(int_err.cause().is_none());
}

#[test]
fn test_sdp_parser_error_address() {
    let v = "127.0.0.a";
    use std::str::FromStr;
    use std::net::IpAddr;
    let addr = IpAddr::from_str(v);
    assert!(addr.is_err());
    // TODO how to verify the output of fmt::Display() ?
    let addr_err = addr.err().unwrap();
    println!("{}", addr_err);
    println!("{}", addr_err.description());
    assert!(addr_err.cause().is_none());
}
<commit_msg>really use sdparsererrors<commit_after>use std::num::ParseIntError;
use std::net::AddrParseError;
use std::fmt;
use std::error;
use std::error::Error;

#[derive(Debug)]
pub enum SdpParserError {
    Line { message: String, line: String },
    Unsupported { message: String, line: String },
    Sequence {
        message: String,
        line: Option<usize>,
    },
    Integer(ParseIntError),
    Address(AddrParseError),
}

impl fmt::Display for SdpParserError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SdpParserError::Line {
                ref message,
                ref line,
            } => write!(f, "Line error: {} in line: {}", message, line),
            SdpParserError::Unsupported {
                ref message,
                ref line,
            } => write!(f, "Unsupported: {} in line: {}", message, line),
            SdpParserError::Sequence { ref message, .. } => {
                write!(f, "Sequence error: {}", message)
            }
            SdpParserError::Integer(ref err) => {
                write!(f, "Integer parsing error: {}", err.description())
            }
            SdpParserError::Address(ref err) => {
                write!(f, "IP address parsing error: {}", err.description())
            }
        }
    }
}

impl error::Error for SdpParserError {
    fn description(&self) -> &str {
        match *self {
            SdpParserError::Line { ref message, .. } |
            SdpParserError::Unsupported { ref message, .. } |
            SdpParserError::Sequence { ref message, .. } => message,
            SdpParserError::Integer(ref err) => err.description(),
            SdpParserError::Address(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            SdpParserError::Integer(ref err) => Some(err),
            SdpParserError::Address(ref err) => Some(err),
            // Can't tell much more about our internal errors
            _ => None,
        }
    }
}

impl From<ParseIntError> for SdpParserError {
    fn from(err: ParseIntError) -> SdpParserError {
        SdpParserError::Integer(err)
    }
}

impl From<AddrParseError> for SdpParserError {
    fn from(err: AddrParseError) -> SdpParserError {
        SdpParserError::Address(err)
    }
}

#[test]
fn test_sdp_parser_error_line() {
    let line = SdpParserError::Line {
        message: "test message".to_string(),
        line: "test line".to_string(),
    };
    // TODO how to verify the output of fmt::Display() ?
    println!("{}", line);
    assert_eq!(line.description(), "test message");
    assert!(line.cause().is_none());
}

#[test]
fn test_sdp_parser_error_unsupported() {
    let unsupported = SdpParserError::Unsupported {
        message: "unsupported message".to_string(),
        line: "unsupported line".to_string(),
    };
    // TODO how to verify the output of fmt::Display() ?
    println!("{}", unsupported);
    assert_eq!(unsupported.description(), "unsupported message");
    assert!(unsupported.cause().is_none());
}

#[test]
fn test_sdp_parser_error_sequence() {
    let sequence1 = SdpParserError::Sequence {
        message: "sequence message".to_string(),
        line: None,
    };
    // TODO how to verify the output of fmt::Display() ?
    println!("{}", sequence1);
    assert_eq!(sequence1.description(), "sequence message");
    assert!(sequence1.cause().is_none());

    let sequence2 = SdpParserError::Sequence {
        message: "another sequence message".to_string(),
        line: Some(5),
    };
    // TODO how to verify the output of fmt::Display() ?
    println!("{}", sequence2);
    assert_eq!(sequence2.description(), "another sequence message");
    assert!(sequence2.cause().is_none());
}

#[test]
fn test_sdp_parser_error_integer() {
    let v = "12a";
    let integer = v.parse::<u64>();
    assert!(integer.is_err());
    let int_err = SdpParserError::Integer(integer.err().unwrap());
    // TODO how to verify the output of fmt::Display() ?
    println!("{}", int_err);
    println!("{}", int_err.description());
    //assert!(int_err.cause().is_none());
}

#[test]
fn test_sdp_parser_error_address() {
    let v = "127.0.0.a";
    use std::str::FromStr;
    use std::net::IpAddr;
    let addr = IpAddr::from_str(v);
    assert!(addr.is_err());
    // TODO how to verify the output of fmt::Display() ?
    let addr_err = SdpParserError::Address(addr.err().unwrap());
    println!("{}", addr_err);
    println!("{}", addr_err.description());
    //assert!(addr_err.cause().is_none());
}
<|endoftext|>


<commit_before>use self::Error::*;
use crate::algorithm::AlgorithmType;
use base64::DecodeError;
use crypto_mac::{InvalidKeyLength, MacError};
use serde_json::Error as JsonError;
use std::fmt;
use std::string::FromUtf8Error;

#[derive(Debug)]
pub enum Error {
    AlgorithmMismatch(AlgorithmType, AlgorithmType),
    NoKeyId,
    NoKeyWithKeyId(String),
    NoHeaderComponent,
    NoClaimsComponent,
    NoSignatureComponent,
    TooManyComponents,
    Format,
    Base64(DecodeError),
    Json(JsonError),
    Utf8(FromUtf8Error),
    RustCryptoMac(MacError),
    RustCryptoMacKeyLength(InvalidKeyLength),
    #[cfg(feature = "openssl")]
    OpenSsl(openssl::error::ErrorStack),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            AlgorithmMismatch(a, b) => {
                write!(f, "Expected algorithm type {:?} but found {:?}", a, b)
            }
            NoKeyId => write!(f, "No key id found"),
            NoKeyWithKeyId(ref kid) => write!(f, "Key with key id {} not found", kid),
            NoHeaderComponent => write!(f, "No header component found in token string"),
            NoClaimsComponent => write!(f, "No claims component found in token string"),
            NoSignatureComponent => write!(f, "No signature component found in token string"),
            TooManyComponents => write!(f, "Too many components found in token string"),
            Format => write!(f, "Format"),
            Base64(ref x) => write!(f, "{}", x),
            Json(ref x) => write!(f, "{}", x),
            Utf8(ref x) => write!(f, "{}", x),
            RustCryptoMac(ref x) => write!(f, "{}", x),
            RustCryptoMacKeyLength(ref x) => write!(f, "{}", x),
            #[cfg(feature = "openssl")]
            OpenSsl(ref x) => write!(f, "{}", x),
        }
    }
}

macro_rules! error_wrap {
    ($f: ty, $e: expr) => {
        impl From<$f> for Error {
            fn from(f: $f) -> Error {
                $e(f)
            }
        }
    };
}

error_wrap!(DecodeError, Base64);
error_wrap!(JsonError, Json);
error_wrap!(FromUtf8Error, Utf8);
error_wrap!(MacError, RustCryptoMac);
error_wrap!(InvalidKeyLength, RustCryptoMacKeyLength);
#[cfg(feature = "openssl")]
error_wrap!(openssl::error::ErrorStack, Error::OpenSsl);
<commit_msg>add impl std::error::Error for Error<commit_after>use self::Error::*;
use crate::algorithm::AlgorithmType;
use base64::DecodeError;
use crypto_mac::{InvalidKeyLength, MacError};
use serde_json::Error as JsonError;
use std::fmt;
use std::string::FromUtf8Error;

#[derive(Debug)]
pub enum Error {
    AlgorithmMismatch(AlgorithmType, AlgorithmType),
    NoKeyId,
    NoKeyWithKeyId(String),
    NoHeaderComponent,
    NoClaimsComponent,
    NoSignatureComponent,
    TooManyComponents,
    Format,
    Base64(DecodeError),
    Json(JsonError),
    Utf8(FromUtf8Error),
    RustCryptoMac(MacError),
    RustCryptoMacKeyLength(InvalidKeyLength),
    #[cfg(feature = "openssl")]
    OpenSsl(openssl::error::ErrorStack),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            AlgorithmMismatch(a, b) => {
                write!(f, "Expected algorithm type {:?} but found {:?}", a, b)
            }
            NoKeyId => write!(f, "No key id found"),
            NoKeyWithKeyId(ref kid) => write!(f, "Key with key id {} not found", kid),
            NoHeaderComponent => write!(f, "No header component found in token string"),
            NoClaimsComponent => write!(f, "No claims component found in token string"),
            NoSignatureComponent => write!(f, "No signature component found in token string"),
            TooManyComponents => write!(f, "Too many components found in token string"),
            Format => write!(f, "Format"),
            Base64(ref x) => write!(f, "{}", x),
            Json(ref x) => write!(f, "{}", x),
            Utf8(ref x) => write!(f, "{}", x),
            RustCryptoMac(ref x) => write!(f, "{}", x),
            RustCryptoMacKeyLength(ref x) => write!(f, "{}", x),
            #[cfg(feature = "openssl")]
            OpenSsl(ref x) => write!(f, "{}", x),
        }
    }
}

impl std::error::Error for Error {}

macro_rules! error_wrap {
    ($f: ty, $e: expr) => {
        impl From<$f> for Error {
            fn from(f: $f) -> Error {
                $e(f)
            }
        }
    };
}

error_wrap!(DecodeError, Base64);
error_wrap!(JsonError, Json);
error_wrap!(FromUtf8Error, Utf8);
error_wrap!(MacError, RustCryptoMac);
error_wrap!(InvalidKeyLength, RustCryptoMacKeyLength);
#[cfg(feature = "openssl")]
error_wrap!(openssl::error::ErrorStack, Error::OpenSsl);
<|endoftext|>


<commit_before>use rand;
use rand::Rng;
use std::collections::VecDeque;
use common::{ParamType, MoveDestination};
use piston_window::*;

pub enum Content {
    Number(u8),
    Mine,
    None
}

struct Cell {
    content: Content,
    revealed: bool,
    marked: bool
}

impl Cell {
    pub fn clear(&mut self) {
        self.content = Content::None;
        self.revealed = false;
        self.marked = false;
    }

    fn reveal(&mut self) -> &Content {
        self.revealed = true;
        &self.content
    }

    fn toggle_mark(&mut self) {
        self.marked = !self.marked;
    }
}

pub struct Field {
    cells: Vec<Cell>,
    width: u32,
    height: u32,
    mines: u32,
    size: u32,
    selected_x: u32,
    selected_y: u32,
    nubmers_total: u32,
    nubmers_opened: u32
}

impl Field {
    pub fn new(width: u32, height: u32, mines: u32) -> Field {
        let mut field = Field {
            width: width,
            height: height,
            cells: vec![],
            mines: mines,
            size: width*height,
            selected_x: width/2,
            selected_y: height/2,
            nubmers_total: 0,
            nubmers_opened: 0
        };
        field.reinit_vec();
        field.fill();
        field
    }

    fn reinit_vec(&mut self) {
        self.cells.clear();
        self.size = self.width*self.height;
        for _i in 0..self.size {
            self.cells.push(Cell{content: Content::None,
                                 revealed: false,
                                 marked: false});
        }
        self.selected_x = self.width/2;
        self.selected_y = self.height/2;
    }

    fn fill(&mut self) {
        self.clear();
        for _i in 0..self.mines {
            let ind = rand::thread_rng().gen_range(0, self.size);
            self.get_cell_mut(ind).content = Content::Mine
        }
        let mut i: i32 = -1;
        let w = self.width as i32;
        while i < (self.size - 1) as i32 {
            i += 1;
            match self.get_content_safe(i) {
                Some(&Content::None) => {
                    let ct_mine = |b| {
                        match b {
                            true => 1,
                            false => 0
                        }
                    };
                     // don`t care about row
                    let mut ct = ct_mine(self.is_mine_safe(i-w)) +
                                 ct_mine(self.is_mine_safe(i+w));
                    if i % w > 0 { // check left side position
                        ct += ct_mine(self.is_mine_safe(i-w-1)) +
                              ct_mine(self.is_mine_safe(i-1)) +
                              ct_mine(self.is_mine_safe(i+w-1));
                    }
                    if i % w < w - 1 { // check right side position
                        ct += ct_mine(self.is_mine_safe(i-w+1)) +
                              ct_mine(self.is_mine_safe(i+1)) +
                              ct_mine(self.is_mine_safe(i+w+1));
                    }
                    if ct > 0 {
                        self.get_cell_mut(i as u32).content = Content::Number(ct);
                        self.nubmers_total += 1;
                    }
                },
                _ => {}
            }
        }
    }

    fn clear(&mut self) {
        for i in 0..self.size {
            self.get_cell_mut(i).clear();
        }
        self.nubmers_opened = 0;
        self.nubmers_total = 0;
    }

    pub fn reveal(&mut self, i: u32) -> &Content {
        if !self.revealed(i) {
            if let &Content::Number(_i) = self.get_cell_mut(i).reveal() {
                self.nubmers_opened += 1;
            }
        }
        &self.get_content(i)
    }

    pub fn revealed(&self, i: u32) -> bool {
        self.get_cell(i).revealed
    }

    pub fn marked(&self, i: u32) -> bool {
        self.get_cell(i).marked
    }

    fn get_cell_mut(&mut self, i:u32) -> &mut Cell {
        self.cells.get_mut(i as usize)
            .unwrap_or_else(|| panic!("Range check error at Field::get_cell_mut ({})", i))
    }

    fn get_cell(& self, i:u32) -> &Cell {
        self.cells.get(i as usize)
            .unwrap_or_else(|| panic!("Range check error at Field::get_cell ({})", i))
    }

    fn get_content_safe(&self, i:i32) -> Option<&Content> {
        if (i < 0) || ((i as u32) >= self.size) {
            None
        } else {
            Some(self.get_content(i as u32))
        }
    }

    pub fn get_content(& self, i: u32) -> &Content {
        &self.get_cell(i).content
    }

    fn is_mine_safe(&self, i: i32) -> bool {
        match self.get_content_safe(i) {
            Some(&Content::Mine) => true,
            _ => false
        }
    }

    pub fn get_width(&self) -> u32 {
        self.width
    }

    pub fn get_height(&self) -> u32 {
        self.height
    }

    pub fn restart(&mut self) {
        self.fill();
    }

    pub fn reveal_all(&mut self) {
        for i in 0..self.size {
            self.get_cell_mut(i).revealed = true;
        }
    }

    pub fn chain_reveal(&mut self, u: u32) {
        if self.marked(u) {
            return;
        }
        let w = self.width as i32;
        // clojure to check for blank cells
        let mut check = |x, d: &mut VecDeque<i32>| {
            match self.get_content_safe(x) {
                Some(&Content::None) => {
                    if !self.revealed(x as u32) {
                        d.push_back(x);
                        self.get_cell_mut(x as u32).marked = false;
                        self.reveal(x as u32);
                    }
                },
                Some(&Content::Number(_n)) => {
                    if !(self.revealed(x as u32)) {
                        self.get_cell_mut(x as u32).marked = false;
                        self.reveal(x as u32);
                    }
                },
                _ => {}
            }
        };
        // BFS initialize
        let deq = &mut VecDeque::new();
        deq.push_back(u as i32);
        // BFS
        while !deq.is_empty() {
            let i = deq.pop_front().unwrap();
            // don`t care about row
            check(i-w, deq);
            check(i+w, deq);
            if i % w > 0 { // check left side position
                check(i-w-1, deq);
                check(i-1, deq);
                check(i+w-1, deq);
            }
            if i % w < w - 1 { // check right side position
                check(i-w+1, deq);
                check(i+1, deq);
                check(i+w+1, deq);
            }
        }
    }

    pub fn draw(&mut self,
            context: Context,
            graphics: &mut G2d,
            field_rect: [u32; 4],
            glyps: &mut Glyphs)
    {
        let cell_w = field_rect[2] / self.get_width();
        let cell_h = field_rect[3] / self.get_height();
        for i in 0..self.get_width() {
            for j in 0..self.get_height() {
                let ind = i + j*self.get_width();
                if self.revealed(ind) {
                    match *self.get_content(i + j*self.get_width()) {
                        Content::Mine => {
                            rectangle([1.0, 0.0, 0.0, 1.0],
                                      [
                                        (field_rect[0] + i*cell_w) as f64,
                                        (field_rect[1] + j*cell_h) as f64,
                                        cell_w as f64,
                                        cell_h as f64
                                      ],
                                      context.transform,
                                      graphics);
                        },
                        Content::Number(n) => {
                            let transform = context.transform.trans((field_rect[0] + i*cell_w) as f64 + 5.0,
                                                                    (field_rect[1] + (j+1)*cell_h) as f64 - 5.0);
                            text::Text::colored([1.0, 1.0, 1.0, 1.0], cell_h).draw(
                                &*n.to_string(),
                                glyps,
                                &context.draw_state,
                                transform,
                                graphics
                            );
                        },
                        Content::None => {
                            rectangle([1.0, 1.0, 1.0, 1.0],
                                      [
                                        (field_rect[0] + i*cell_w) as f64,
                                        (field_rect[1] + j*cell_h) as f64,
                                        cell_w as f64,
                                        cell_h as f64
                                      ],
                                      context.transform,
                                      graphics);
                        }
                    }
                }
                if self.marked(ind) {
                    rectangle([0.0, 1.0, 0.0, 0.75],
                              [
                                (field_rect[0] + i*cell_w) as f64,
                                (field_rect[1] + j*cell_h) as f64,
                                cell_w as f64,
                                cell_h as f64
                              ],
                              context.transform,
                              graphics);
                }
            }
        }
        rectangle([0.5, 0.5, 0.5, 0.75],
                  [
                    (field_rect[0] + self.selected_x*cell_w) as f64,
                    (field_rect[1] + self.selected_y*cell_h) as f64,
                    cell_w as f64,
                    cell_h as f64
                  ],
                  context.transform,
                  graphics);
        for i in 0..self.get_width() + 1 {
            line::Line::new([0.5, 0.5, 0.5, 1.0], 1.0)
                .draw([
                        (field_rect[0] + i*cell_w) as f64,
                        field_rect[1] as f64,
                        (field_rect[0] + i*cell_w) as f64,
                        (field_rect[1] + field_rect[3]) as f64
                      ],
                      &context.draw_state,
                      context.transform,
                      graphics);
        }
        for i in 0..self.get_height() + 1 {
            line::Line::new([0.5, 0.5, 0.5, 1.0], 1.0)
                .draw([
                        field_rect[0] as f64,
                        (field_rect[1] + i*cell_h) as f64,
                        (field_rect[0] + field_rect[2]) as f64,
                        (field_rect[1] + i*cell_h) as f64
                      ],
                      &context.draw_state,
                      context.transform,
                      graphics);
        }
    }

    pub fn move_selection(&mut self, dest: MoveDestination) {
        match dest {
            MoveDestination::Up => {
                if self.selected_y > 0 {
                    self.selected_y -= 1;
                }
            },
            MoveDestination::Down => {
                if self.selected_y < self.height - 1 {
                    self.selected_y += 1;
                }
            },
            MoveDestination::Left => {
                if self.selected_x > 0 {
                    self.selected_x -= 1;
                }
            },
            MoveDestination::Right => {
                if self.selected_x < self.width - 1 {
                    self.selected_x += 1;
                }
            }
        }
    }

    pub fn get_selected_ind(&self) -> u32 {
        self.selected_x + self.selected_y*self.width
    }

    pub fn is_victory(&self) -> bool {
        self.nubmers_total == self.nubmers_opened
    }

    pub fn reinit_field(&mut self, num: u32, param: ParamType) {
        let mut restart_neded = false;
        match param {
            ParamType::Height => {
                if self.height != num {
                    self.height = num;
                    self.reinit_vec();
                    restart_neded = true;
                }
            }
            ParamType::Width => {
                if self.width != num {
                    self.width = num;
                    self.reinit_vec();
                    restart_neded = true;
                }
            }
            ParamType::Mines => {
                if self.mines != num {
                    self.mines = num;
                    restart_neded = true;
                }
            }
        }
        if restart_neded {
            self.restart();
        }
    }

    pub fn toggle_mark(&mut self, i: u32) {
        self.get_cell_mut(i).toggle_mark();
    }
}<commit_msg>style: change bg color of number tile to match empty tiles<commit_after>use rand;
use rand::Rng;
use std::collections::VecDeque;
use common::{ParamType, MoveDestination};
use piston_window::*;

pub enum Content {
    Number(u8),
    Mine,
    None
}

struct Cell {
    content: Content,
    revealed: bool,
    marked: bool
}

impl Cell {
    pub fn clear(&mut self) {
        self.content = Content::None;
        self.revealed = false;
        self.marked = false;
    }

    fn reveal(&mut self) -> &Content {
        self.revealed = true;
        &self.content
    }

    fn toggle_mark(&mut self) {
        self.marked = !self.marked;
    }
}

pub struct Field {
    cells: Vec<Cell>,
    width: u32,
    height: u32,
    mines: u32,
    size: u32,
    selected_x: u32,
    selected_y: u32,
    nubmers_total: u32,
    nubmers_opened: u32
}

impl Field {
    pub fn new(width: u32, height: u32, mines: u32) -> Field {
        let mut field = Field {
            width: width,
            height: height,
            cells: vec![],
            mines: mines,
            size: width*height,
            selected_x: width/2,
            selected_y: height/2,
            nubmers_total: 0,
            nubmers_opened: 0
        };
        field.reinit_vec();
        field.fill();
        field
    }

    fn reinit_vec(&mut self) {
        self.cells.clear();
        self.size = self.width*self.height;
        for _i in 0..self.size {
            self.cells.push(Cell{content: Content::None,
                                 revealed: false,
                                 marked: false});
        }
        self.selected_x = self.width/2;
        self.selected_y = self.height/2;
    }

    fn fill(&mut self) {
        self.clear();
        for _i in 0..self.mines {
            let ind = rand::thread_rng().gen_range(0, self.size);
            self.get_cell_mut(ind).content = Content::Mine
        }
        let mut i: i32 = -1;
        let w = self.width as i32;
        while i < (self.size - 1) as i32 {
            i += 1;
            match self.get_content_safe(i) {
                Some(&Content::None) => {
                    let ct_mine = |b| {
                        match b {
                            true => 1,
                            false => 0
                        }
                    };
                     // don`t care about row
                    let mut ct = ct_mine(self.is_mine_safe(i-w)) +
                                 ct_mine(self.is_mine_safe(i+w));
                    if i % w > 0 { // check left side position
                        ct += ct_mine(self.is_mine_safe(i-w-1)) +
                              ct_mine(self.is_mine_safe(i-1)) +
                              ct_mine(self.is_mine_safe(i+w-1));
                    }
                    if i % w < w - 1 { // check right side position
                        ct += ct_mine(self.is_mine_safe(i-w+1)) +
                              ct_mine(self.is_mine_safe(i+1)) +
                              ct_mine(self.is_mine_safe(i+w+1));
                    }
                    if ct > 0 {
                        self.get_cell_mut(i as u32).content = Content::Number(ct);
                        self.nubmers_total += 1;
                    }
                },
                _ => {}
            }
        }
    }

    fn clear(&mut self) {
        for i in 0..self.size {
            self.get_cell_mut(i).clear();
        }
        self.nubmers_opened = 0;
        self.nubmers_total = 0;
    }

    pub fn reveal(&mut self, i: u32) -> &Content {
        if !self.revealed(i) {
            if let &Content::Number(_i) = self.get_cell_mut(i).reveal() {
                self.nubmers_opened += 1;
            }
        }
        &self.get_content(i)
    }

    pub fn revealed(&self, i: u32) -> bool {
        self.get_cell(i).revealed
    }

    pub fn marked(&self, i: u32) -> bool {
        self.get_cell(i).marked
    }

    fn get_cell_mut(&mut self, i:u32) -> &mut Cell {
        self.cells.get_mut(i as usize)
            .unwrap_or_else(|| panic!("Range check error at Field::get_cell_mut ({})", i))
    }

    fn get_cell(& self, i:u32) -> &Cell {
        self.cells.get(i as usize)
            .unwrap_or_else(|| panic!("Range check error at Field::get_cell ({})", i))
    }

    fn get_content_safe(&self, i:i32) -> Option<&Content> {
        if (i < 0) || ((i as u32) >= self.size) {
            None
        } else {
            Some(self.get_content(i as u32))
        }
    }

    pub fn get_content(& self, i: u32) -> &Content {
        &self.get_cell(i).content
    }

    fn is_mine_safe(&self, i: i32) -> bool {
        match self.get_content_safe(i) {
            Some(&Content::Mine) => true,
            _ => false
        }
    }

    pub fn get_width(&self) -> u32 {
        self.width
    }

    pub fn get_height(&self) -> u32 {
        self.height
    }

    pub fn restart(&mut self) {
        self.fill();
    }

    pub fn reveal_all(&mut self) {
        for i in 0..self.size {
            self.get_cell_mut(i).revealed = true;
        }
    }

    pub fn chain_reveal(&mut self, u: u32) {
        if self.marked(u) {
            return;
        }
        let w = self.width as i32;
        // clojure to check for blank cells
        let mut check = |x, d: &mut VecDeque<i32>| {
            match self.get_content_safe(x) {
                Some(&Content::None) => {
                    if !self.revealed(x as u32) {
                        d.push_back(x);
                        self.get_cell_mut(x as u32).marked = false;
                        self.reveal(x as u32);
                    }
                },
                Some(&Content::Number(_n)) => {
                    if !(self.revealed(x as u32)) {
                        self.get_cell_mut(x as u32).marked = false;
                        self.reveal(x as u32);
                    }
                },
                _ => {}
            }
        };
        // BFS initialize
        let deq = &mut VecDeque::new();
        deq.push_back(u as i32);
        // BFS
        while !deq.is_empty() {
            let i = deq.pop_front().unwrap();
            // don`t care about row
            check(i-w, deq);
            check(i+w, deq);
            if i % w > 0 { // check left side position
                check(i-w-1, deq);
                check(i-1, deq);
                check(i+w-1, deq);
            }
            if i % w < w - 1 { // check right side position
                check(i-w+1, deq);
                check(i+1, deq);
                check(i+w+1, deq);
            }
        }
    }

    pub fn draw(&mut self,
            context: Context,
            graphics: &mut G2d,
            field_rect: [u32; 4],
            glyps: &mut Glyphs)
    {
        let cell_w = field_rect[2] / self.get_width();
        let cell_h = field_rect[3] / self.get_height();
        for i in 0..self.get_width() {
            for j in 0..self.get_height() {
                let ind = i + j*self.get_width();
                if self.revealed(ind) {
                    match *self.get_content(i + j*self.get_width()) {
                        Content::Mine => {
                            rectangle([1.0, 0.0, 0.0, 1.0],
                                      [
                                        (field_rect[0] + i*cell_w) as f64,
                                        (field_rect[1] + j*cell_h) as f64,
                                        cell_w as f64,
                                        cell_h as f64
                                      ],
                                      context.transform,
                                      graphics);
                        },
                        Content::Number(n) => {
                            let transform = context.transform.trans((field_rect[0] + i*cell_w) as f64 + 5.0,
                                                                    (field_rect[1] + (j+1)*cell_h) as f64 - 5.0);
                            rectangle([1.0, 1.0, 1.0, 1.0],
                                      [
                                        (field_rect[0] + i*cell_w) as f64,
                                        (field_rect[1] + j*cell_h) as f64,
                                        cell_w as f64,
                                        cell_h as f64
                                      ],
                                      context.transform,
                                      graphics);
                            text::Text::colored([0.3, 0.3, 0.3, 1.0], cell_h).draw(
                                &*n.to_string(),
                                glyps,
                                &context.draw_state,
                                transform,
                                graphics
                            );
                        },
                        Content::None => {
                            rectangle([1.0, 1.0, 1.0, 1.0],
                                      [
                                        (field_rect[0] + i*cell_w) as f64,
                                        (field_rect[1] + j*cell_h) as f64,
                                        cell_w as f64,
                                        cell_h as f64
                                      ],
                                      context.transform,
                                      graphics);
                        }
                    }
                }
                if self.marked(ind) {
                    rectangle([0.0, 1.0, 0.0, 0.75],
                              [
                                (field_rect[0] + i*cell_w) as f64,
                                (field_rect[1] + j*cell_h) as f64,
                                cell_w as f64,
                                cell_h as f64
                              ],
                              context.transform,
                              graphics);
                }
            }
        }
        rectangle([0.5, 0.5, 0.5, 0.75],
                  [
                    (field_rect[0] + self.selected_x*cell_w) as f64,
                    (field_rect[1] + self.selected_y*cell_h) as f64,
                    cell_w as f64,
                    cell_h as f64
                  ],
                  context.transform,
                  graphics);
        for i in 0..self.get_width() + 1 {
            line::Line::new([0.5, 0.5, 0.5, 1.0], 1.0)
                .draw([
                        (field_rect[0] + i*cell_w) as f64,
                        field_rect[1] as f64,
                        (field_rect[0] + i*cell_w) as f64,
                        (field_rect[1] + field_rect[3]) as f64
                      ],
                      &context.draw_state,
                      context.transform,
                      graphics);
        }
        for i in 0..self.get_height() + 1 {
            line::Line::new([0.5, 0.5, 0.5, 1.0], 1.0)
                .draw([
                        field_rect[0] as f64,
                        (field_rect[1] + i*cell_h) as f64,
                        (field_rect[0] + field_rect[2]) as f64,
                        (field_rect[1] + i*cell_h) as f64
                      ],
                      &context.draw_state,
                      context.transform,
                      graphics);
        }
    }

    pub fn move_selection(&mut self, dest: MoveDestination) {
        match dest {
            MoveDestination::Up => {
                if self.selected_y > 0 {
                    self.selected_y -= 1;
                }
            },
            MoveDestination::Down => {
                if self.selected_y < self.height - 1 {
                    self.selected_y += 1;
                }
            },
            MoveDestination::Left => {
                if self.selected_x > 0 {
                    self.selected_x -= 1;
                }
            },
            MoveDestination::Right => {
                if self.selected_x < self.width - 1 {
                    self.selected_x += 1;
                }
            }
        }
    }

    pub fn get_selected_ind(&self) -> u32 {
        self.selected_x + self.selected_y*self.width
    }

    pub fn is_victory(&self) -> bool {
        self.nubmers_total == self.nubmers_opened
    }

    pub fn reinit_field(&mut self, num: u32, param: ParamType) {
        let mut restart_neded = false;
        match param {
            ParamType::Height => {
                if self.height != num {
                    self.height = num;
                    self.reinit_vec();
                    restart_neded = true;
                }
            }
            ParamType::Width => {
                if self.width != num {
                    self.width = num;
                    self.reinit_vec();
                    restart_neded = true;
                }
            }
            ParamType::Mines => {
                if self.mines != num {
                    self.mines = num;
                    restart_neded = true;
                }
            }
        }
        if restart_neded {
            self.restart();
        }
    }

    pub fn toggle_mark(&mut self, i: u32) {
        self.get_cell_mut(i).toggle_mark();
    }
}<|endoftext|>


<commit_before>use std::fmt::{self, Display};

#[derive(Debug, Clone, Eq, Hash)]
pub struct Ident(String);

impl Ident {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        t.into()
    }
}

impl<'a> From<&'a str> for Ident {
    fn from(s: &str) -> Self {
        Ident(s.to_owned())
    }
}

impl From<String> for Ident {
    fn from(s: String) -> Self {
        Ident(s)
    }
}

impl From<usize> for Ident {
    fn from(u: usize) -> Self {
        Ident(u.to_string())
    }
}

impl AsRef<str> for Ident {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

impl Display for Ident {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(formatter)
    }
}

impl<T: ?Sized> PartialEq<T> for Ident
    where T: AsRef<str>
{
    fn eq(&self, other: &T) -> bool {
        self.0 == other.as_ref()
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use nom::IResult;
    use space::skip_whitespace;
    use unicode_xid::UnicodeXID;

    pub fn ident(input: &str) -> IResult<&str, Ident> {
        let (rest, id) = match word(input) {
            IResult::Done(rest, id) => (rest, id),
            IResult::Error => return IResult::Error,
        };

        match id.as_ref() {
            // From https://doc.rust-lang.org/grammar.html#keywords
            "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue" |
            "crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" |
            "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" | "mod" | "move" |
            "mut" | "offsetof" | "override" | "priv" | "proc" | "pub" | "pure" | "ref" |
            "return" | "Self" | "self" | "sizeof" | "static" | "struct" | "super" | "trait" |
            "true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" |
            "while" | "yield" => IResult::Error,
            _ => IResult::Done(rest, id),
        }
    }

    pub fn word(mut input: &str) -> IResult<&str, Ident> {
        input = skip_whitespace(input);

        let mut chars = input.char_indices();
        match chars.next() {
            Some((_, ch)) if UnicodeXID::is_xid_start(ch) || ch == '_' => {}
            _ => return IResult::Error,
        }

        while let Some((i, ch)) = chars.next() {
            if !UnicodeXID::is_xid_continue(ch) {
                return IResult::Done(&input[i..], input[..i].into());
            }
        }

        IResult::Done("", input.into())
    }

    pub fn wordlike(mut input: &str) -> IResult<&str, Ident> {
        input = skip_whitespace(input);

        for (i, ch) in input.char_indices() {
            if !UnicodeXID::is_xid_start(ch) && !UnicodeXID::is_xid_continue(ch) {
                return if i == 0 {
                    IResult::Error
                } else {
                    IResult::Done(&input[i..], input[..i].into())
                };
            }
        }

        IResult::Done("", input.into())
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Ident {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append(self.as_ref())
        }
    }
}
<commit_msg>Wordlike is only used for expressions<commit_after>use std::fmt::{self, Display};

#[derive(Debug, Clone, Eq, Hash)]
pub struct Ident(String);

impl Ident {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        t.into()
    }
}

impl<'a> From<&'a str> for Ident {
    fn from(s: &str) -> Self {
        Ident(s.to_owned())
    }
}

impl From<String> for Ident {
    fn from(s: String) -> Self {
        Ident(s)
    }
}

impl From<usize> for Ident {
    fn from(u: usize) -> Self {
        Ident(u.to_string())
    }
}

impl AsRef<str> for Ident {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

impl Display for Ident {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(formatter)
    }
}

impl<T: ?Sized> PartialEq<T> for Ident
    where T: AsRef<str>
{
    fn eq(&self, other: &T) -> bool {
        self.0 == other.as_ref()
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use nom::IResult;
    use space::skip_whitespace;
    use unicode_xid::UnicodeXID;

    pub fn ident(input: &str) -> IResult<&str, Ident> {
        let (rest, id) = match word(input) {
            IResult::Done(rest, id) => (rest, id),
            IResult::Error => return IResult::Error,
        };

        match id.as_ref() {
            // From https://doc.rust-lang.org/grammar.html#keywords
            "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue" |
            "crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" |
            "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" | "mod" | "move" |
            "mut" | "offsetof" | "override" | "priv" | "proc" | "pub" | "pure" | "ref" |
            "return" | "Self" | "self" | "sizeof" | "static" | "struct" | "super" | "trait" |
            "true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" |
            "while" | "yield" => IResult::Error,
            _ => IResult::Done(rest, id),
        }
    }

    pub fn word(mut input: &str) -> IResult<&str, Ident> {
        input = skip_whitespace(input);

        let mut chars = input.char_indices();
        match chars.next() {
            Some((_, ch)) if UnicodeXID::is_xid_start(ch) || ch == '_' => {}
            _ => return IResult::Error,
        }

        while let Some((i, ch)) = chars.next() {
            if !UnicodeXID::is_xid_continue(ch) {
                return IResult::Done(&input[i..], input[..i].into());
            }
        }

        IResult::Done("", input.into())
    }

    #[cfg(feature = "full")]
    pub fn wordlike(mut input: &str) -> IResult<&str, Ident> {
        input = skip_whitespace(input);

        for (i, ch) in input.char_indices() {
            if !UnicodeXID::is_xid_start(ch) && !UnicodeXID::is_xid_continue(ch) {
                return if i == 0 {
                    IResult::Error
                } else {
                    IResult::Done(&input[i..], input[..i].into())
                };
            }
        }

        IResult::Done("", input.into())
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Ident {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append(self.as_ref())
        }
    }
}
<|endoftext|>


<commit_before>#![crate_type = "lib"]
extern crate libc;
extern crate usb;
extern crate serialize;

use std::io::timer::sleep;
use std::iter::range_inclusive;
use std::fmt::{Show, Formatter, FormatError};
use std::default::Default;
use usb::libusb;

bitflags!(
  flags AnalogChannel: u8 {
      static A1 = 1,
      static A2 = 2
  }
)

bitflags!(
  flags DigitalChannel: u8 {
    static Zero = 0,
    static D1 = 1,
    static D2 = 2,
    static D3 = 4,
    static D4 = 8,
    static D5 = 16,
    static D6 = 32,
    static D7 = 64,
    static D8 = 128,
    static All = 255
  }
)

bitflags!(
    flags CardAddress: uint {
        static Card1 = 0x5500,
        static Card2 = 0x5501,
        static Card3 = 0x5502,
        static Card4 = 0x5503,
        static CardAny = 0x0
    }
)

static VendorId: uint = 0x10cfu;

#[deriving(Show)]
enum Packet {
    Reset,
    SetAnalogDigital(u8, u8, u8),
    Status(u8, u8, u8, u8)
}

#[deriving(Default)]
struct State {
    dig: u8,
    ana1: u8,
    ana2: u8
}

pub struct K8055 {
    dev: usb::Device,
    hd: Option<usb::DeviceHandle>,
    state: State
}

impl K8055 {
    pub fn new() -> Option<K8055> {
        K8055::new_addr(CardAny)
    }

    pub fn new_addr(addr: CardAddress) -> Option<K8055> {
        let c = usb::Context::new();
        let d = if addr == CardAny {
            K8055::find_any_k8055(&c)
        } else {
            c.find_by_vid_pid(VendorId, addr.bits)
        };

        if d.is_some() {
            return Some(K8055{ dev: d.unwrap(), hd: None, state: Default::default() })
        } else {
            return None
        }
    }

    pub fn open(&mut self) -> bool {
      // device already open
      if self.hd.is_some() { return true }
      match self.dev.open() {
          Ok(h) => {
              self.hd = Some(h);
              return true
          }
          Err(_) => return false
      }
    }

    pub fn reset(&mut self) -> bool {
        self.write(&SetAnalogDigital(0u8, 0u8, 0u8))
    }

    pub fn write_digital_out(&mut self, d: DigitalChannel) -> bool {
        let p = &SetAnalogDigital(d.bits, self.state.ana1, self.state.ana2);
        self.write(p)
    }

    pub fn write_digital_out_mask(&mut self, d: DigitalChannel, mask: DigitalChannel) -> bool {
        self.write_digital_out(d & mask)
    }

    pub fn get_digital_out(&mut self) -> DigitalChannel {
        DigitalChannel::from_bits(self.state.dig).unwrap()
    }

    pub fn get_digital_out_mask(&mut self, d: DigitalChannel) -> DigitalChannel {
        DigitalChannel::from_bits(self.state.dig).unwrap() & d
    }

    pub fn read_digital_in(&mut self) -> Option<DigitalChannel> {
        match self.read() {
            Some(Status(dig, _, _, _)) => Some(DigitalChannel::from_bits(dig).unwrap()),
            _ => None
        }
    }

    pub fn read_digital_in_mask(&mut self, mask: DigitalChannel) -> Option<DigitalChannel> {
        match self.read_digital_in() {
            Some(c) => Some(c & mask),
            _ => None
        }
    }

// private

    fn find_any_k8055(c: &usb::Context) -> Option<usb::Device> {
        for pid in range_inclusive(Card1.bits, Card4.bits) {
          let d = c.find_by_vid_pid(VendorId, pid);
          if d.is_some() { return d }
        }
        None
    }

    fn write(&mut self, p: &Packet) -> bool {
        match self.hd {
          Some(ref hd) => {
              K8055::detach_and_claim(hd);
              let data = match K8055::encode(p) {
                  Some(d) => d,
                  None => return false
              };

              match hd.write(0x1, libusb::LIBUSB_TRANSFER_TYPE_INTERRUPT, data) {
                  Ok(_) => {
                      // update the internal state on output changes
                      match *p {
                          SetAnalogDigital(d, a1, a2) => {
                              self.state = State{dig: d, ana1: a1, ana2: a2};
                          }
                          _ => ()
                      }
                      return true
                  }
                  Err(_) => return false
              }
          }
          None => return false
        }
    }

    fn read(&mut self) -> Option<Packet> {
        match self.hd {
          Some(ref hd) => {
            K8055::detach_and_claim(hd);
            match hd.read(0x81, libusb::LIBUSB_TRANSFER_TYPE_INTERRUPT, 8) {
              Ok(data) => K8055::decode(data.as_slice()),
              Err(_) => None
            }
          }
          None => None
        }
    }

    fn encode(p: &Packet) -> Option<[u8, ..8]> {
      match *p {
          Reset => Some([0u8, ..8]),
          SetAnalogDigital(dig, ana1, ana2) => Some([5u8, dig, ana1, ana2,
                                                     0u8, 0u8, 0u8, 0u8]),
          _ => None
      }
    }

    fn decode(d: &[u8]) -> Option<Packet> {
       match d {
          [dig, st, ana1, ana2, _, _, _, _] => Some(Status(dig, st, ana1, ana2)),
          _ => None
       }
    }

    fn detach_and_claim(hd: &usb::DeviceHandle ) {
      unsafe {
        if libusb::libusb_kernel_driver_active(hd.ptr(), 0) == 1 {
          if libusb::libusb_detach_kernel_driver(hd.ptr(), 0) != 0 {
            fail!("Can't detach usb kernel driver");
          }
        }
      }
      hd.claim_interface(0u);
    }

}

impl Show for K8055 {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
      write!(f, "K8055( bus: {}, address: {} )", self.dev.bus(), self.dev.address())
    }
}

#[test()]
fn find_and_open() {
  let k = K8055::new();
  assert!(k.is_some());
  let mut k = k.unwrap();
  assert!(k.open());
  assert!(K8055::new_addr(Card2).is_none());
  assert!(K8055::new_addr(Card3).is_none());
  assert!(K8055::new_addr(Card4).is_none());
}

#[test()]
fn write_and_read_digital() {
  let k = K8055::new();
  assert!(k.is_some());
  let mut k = k.unwrap();
  assert!(k.open());
  assert!(k.get_digital_out() == Zero);
  for i in range(0u, 8) {
    assert!(k.write_digital_out(DigitalChannel::from_bits(1u8<<i).unwrap()));
    assert!(k.get_digital_out() == DigitalChannel::from_bits(1u8<<i).unwrap());
    sleep(100);
  }
  assert!(k.reset());
  assert!(k.get_digital_out() == Zero);

  assert!(k.write_digital_out_mask(D1 | D2 | D3, D2));
  assert!(k.get_digital_out() == D2);
  assert!(k.reset());
}

<commit_msg>Add analog read write functionality<commit_after>#![crate_type = "lib"]
extern crate libc;
extern crate usb;
extern crate serialize;

use std::iter::range_inclusive;
use std::fmt::{Show, Formatter, FormatError};
use std::default::Default;
use usb::libusb;

#[deriving(PartialEq, PartialOrd, Show)]
pub enum AnalogChannel {
      A1(u8),
      A2(u8)
}

bitflags!(
  flags DigitalChannel: u8 {
    static Zero = 0,
    static D1 = 1,
    static D2 = 2,
    static D3 = 4,
    static D4 = 8,
    static D5 = 16,
    static D6 = 32,
    static D7 = 64,
    static D8 = 128,
    static All = 255
  }
)

bitflags!(
    flags CardAddress: uint {
        static Card1 = 0x5500,
        static Card2 = 0x5501,
        static Card3 = 0x5502,
        static Card4 = 0x5503,
        static CardAny = 0x0
    }
)

static VendorId: uint = 0x10cfu;

#[deriving(Show)]
enum Packet {
    Reset,
    SetAnalogDigital(u8, u8, u8),
    Status(u8, u8, u8, u8)
}

#[deriving(Default)]
struct State {
    dig: u8,
    ana1: u8,
    ana2: u8
}

pub struct K8055 {
    dev: usb::Device,
    hd: Option<usb::DeviceHandle>,
    state: State
}

impl K8055 {
    pub fn new() -> Option<K8055> {
        K8055::new_addr(CardAny)
    }

    pub fn new_addr(addr: CardAddress) -> Option<K8055> {
        let c = usb::Context::new();
        let d = if addr == CardAny {
            K8055::find_any_k8055(&c)
        } else {
            c.find_by_vid_pid(VendorId, addr.bits)
        };

        if d.is_some() {
            return Some(K8055{ dev: d.unwrap(), hd: None, state: Default::default() })
        } else {
            return None
        }
    }

    pub fn open(&mut self) -> bool {
      // device already open
      if self.hd.is_some() { return true }
      match self.dev.open() {
          Ok(h) => {
              self.hd = Some(h);
              return true
          }
          Err(_) => return false
      }
    }

    pub fn reset(&mut self) -> bool {
        self.write(&SetAnalogDigital(0u8, 0u8, 0u8))
    }

// digital
    pub fn write_digital_out(&mut self, d: DigitalChannel) -> bool {
        let p = &SetAnalogDigital(d.bits, self.state.ana1, self.state.ana2);
        self.write(p)
    }

    pub fn write_digital_out_mask(&mut self, d: DigitalChannel, mask: DigitalChannel) -> bool {
        self.write_digital_out(d & mask)
    }

    pub fn get_digital_out(&mut self) -> DigitalChannel {
        DigitalChannel::from_bits(self.state.dig).unwrap()
    }

    pub fn get_digital_out_mask(&mut self, d: DigitalChannel) -> DigitalChannel {
        DigitalChannel::from_bits(self.state.dig).unwrap() & d
    }

    pub fn read_digital_in(&mut self) -> Option<DigitalChannel> {
        match self.read() {
            Some(Status(dig, _, _, _)) => Some(DigitalChannel::from_bits(dig).unwrap()),
            _ => None
        }
    }

    pub fn read_digital_in_mask(&mut self, mask: DigitalChannel) -> Option<DigitalChannel> {
        match self.read_digital_in() {
            Some(c) => Some(c & mask),
            _ => None
        }
    }

// analog
    pub fn write_analog_out(&mut self, a: AnalogChannel) -> bool {
      let p = match a {
          A1(v) => SetAnalogDigital(self.state.dig, v, self.state.ana2),
          A2(v) => SetAnalogDigital(self.state.dig, self.state.ana1, v)
      };
      self.write(&p)
    }

    pub fn get_analog_out1(&mut self) -> AnalogChannel {
        A1(self.state.ana1)
    }

    pub fn get_analog_out2(&mut self) -> AnalogChannel {
        A2(self.state.ana2)
    }

    pub fn read_analog_in1(&mut self) -> Option<AnalogChannel> {
        match self.read() {
            Some(Status(_, _, a1, _)) => Some(A1(a1)),
            _ => None
        }
    }

    pub fn read_analog_in2(&mut self) -> Option<AnalogChannel> {
        match self.read() {
            Some(Status(_, _, _, a2)) => Some(A2(a2)),
            _ => None
        }
    }

// private

    fn find_any_k8055(c: &usb::Context) -> Option<usb::Device> {
        for pid in range_inclusive(Card1.bits, Card4.bits) {
          let d = c.find_by_vid_pid(VendorId, pid);
          if d.is_some() { return d }
        }
        None
    }

    fn write(&mut self, p: &Packet) -> bool {
        match self.hd {
          Some(ref hd) => {
              K8055::detach_and_claim(hd);
              let data = match K8055::encode(p) {
                  Some(d) => d,
                  None => return false
              };

              match hd.write(0x1, libusb::LIBUSB_TRANSFER_TYPE_INTERRUPT, data) {
                  Ok(_) => {
                      // update the internal state on output changes
                      match *p {
                          SetAnalogDigital(d, a1, a2) => {
                              self.state = State{dig: d, ana1: a1, ana2: a2};
                          }
                          _ => ()
                      }
                      return true
                  }
                  Err(_) => return false
              }
          }
          None => return false
        }
    }

    fn read(&mut self) -> Option<Packet> {
        match self.hd {
          Some(ref hd) => {
            K8055::detach_and_claim(hd);
            match hd.read(0x81, libusb::LIBUSB_TRANSFER_TYPE_INTERRUPT, 8) {
              Ok(data) => K8055::decode(data.as_slice()),
              Err(_) => None
            }
          }
          None => None
        }
    }

    fn encode(p: &Packet) -> Option<[u8, ..8]> {
      match *p {
          Reset => Some([0u8, ..8]),
          SetAnalogDigital(dig, ana1, ana2) => Some([5u8, dig, ana1, ana2,
                                                     0u8, 0u8, 0u8, 0u8]),
          _ => None
      }
    }

    fn decode(d: &[u8]) -> Option<Packet> {
       match d {
          [dig, st, ana1, ana2, _, _, _, _] => Some(Status(dig, st, ana1, ana2)),
          _ => None
       }
    }

    fn detach_and_claim(hd: &usb::DeviceHandle ) {
      unsafe {
        if libusb::libusb_kernel_driver_active(hd.ptr(), 0) == 1 {
          if libusb::libusb_detach_kernel_driver(hd.ptr(), 0) != 0 {
            fail!("Can't detach usb kernel driver");
          }
        }
      }
      hd.claim_interface(0u);
    }

}

impl Show for K8055 {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
      write!(f, "K8055( bus: {}, address: {} )", self.dev.bus(), self.dev.address())
    }
}

#[test()]
fn find_and_open() {
  let k = K8055::new();
  assert!(k.is_some());
  let mut k = k.unwrap();
  assert!(k.open());
  assert!(K8055::new_addr(Card2).is_none());
  assert!(K8055::new_addr(Card3).is_none());
  assert!(K8055::new_addr(Card4).is_none());
}

#[test()]
fn write_and_read_digital() {
  use std::io::timer::sleep;

  let k = K8055::new();
  assert!(k.is_some());
  let mut k = k.unwrap();
  assert!(k.open());
  assert!(k.get_digital_out() == Zero);
  for i in range(0u, 8) {
    assert!(k.write_digital_out(DigitalChannel::from_bits(1u8<<i).unwrap()));
    assert!(k.get_digital_out() == DigitalChannel::from_bits(1u8<<i).unwrap());
    sleep(100);
  }
  assert!(k.reset());
  assert!(k.get_digital_out() == Zero);

  assert!(k.write_digital_out_mask(D1 | D2 | D3, D2));
  assert!(k.get_digital_out() == D2);
  assert!(k.reset());
  sleep(1000);
}

#[test()]
fn write_and_read_analog() {
  use std::io::timer::sleep;

  let k = K8055::new();
  assert!(k.is_some());
  let mut k = k.unwrap();
  assert!(k.open());
  assert!(k.get_analog_out1() == A1(0u8));
  assert!(k.get_analog_out2() == A2(0u8));
  for i in range(0u8, 255) {
    assert!(k.write_analog_out(A1(i)));
    assert!(k.write_analog_out(A2(255-i)));
    sleep(10);
  }
  assert!(k.reset());
  sleep(1000);
}

<|endoftext|>


<commit_before>use chunk::Chunk;
use tile::Tile;
use std::collections::HashMap;

const DEF_CHUNK_WIDTH: i32 = 100;
const DEF_CHUNK_HEIGHT: i32 = 100;

pub struct TilesLayer<T> {
    x_offset: i32,
    y_offset: i32,
    chunks: Vec<Chunk<T>>,
}

impl<T> TilesLayer<T> {
    pub fn new() -> TilesLayer<T> {
        TilesLayer {
            x_offset: 0,
            y_offset: 0,
            chunks: Vec::<Chunk<T>>::new(),
        }
    }

    #[inline]
    fn get_rel_x(&self, x: i32) -> i32 {
        x - self.x_offset
    }

    #[inline]
    fn get_rel_y(&self, y: i32) -> i32 {
        y - self.y_offset
    }

    pub fn add_tile(&mut self, x: i32, y: i32, w: u32, h: u32, tile_info: T) {
        let mut chunk_ind: i32 = -1;
        let rel_x = self.get_rel_x(x);
        let rel_y = self.get_rel_y(y);
        for i in 0..self.chunks.len() {
            let chunk = &self.chunks[i];
            if (rel_x > chunk.x) && (rel_x < chunk.x + chunk.width as i32) &&
               (rel_y > chunk.y) && (rel_y < chunk.y + chunk.height as i32) {
                chunk_ind = i as i32;
                break;
            }
        }
        if chunk_ind < 0 {
            self.chunks.push(Chunk::new((rel_x/DEF_CHUNK_WIDTH)*DEF_CHUNK_WIDTH,
                                        (rel_y/DEF_CHUNK_HEIGHT)*DEF_CHUNK_HEIGHT,
                                        DEF_CHUNK_WIDTH as u32,
                                        DEF_CHUNK_HEIGHT as u32));
            chunk_ind = (self.chunks.len()-1) as i32;
        }
        self.chunks[chunk_ind as usize].add_tile(rel_x, rel_y, w, h, tile_info);
    }

    pub fn get_tiles(&self, cam_x: f64, cam_y: f64, cam_w: i32, cam_h: i32) -> HashMap<(i32, i32,), &Tile<T>> {
        let rel_x = self.get_rel_x(cam_x as i32);
        let rel_y = self.get_rel_y(cam_y as i32);
        let mut result = HashMap::<(i32, i32), &Tile<T>>::new();
        for chunk in self.chunks.iter() {
            if (rel_x + cam_w > chunk.x) && (rel_x < chunk.x + chunk.width as i32) &&
               (rel_y + cam_h > chunk.y) && (rel_y < chunk.y + chunk.height as i32) {
                chunk.get_tiles(&mut result);
            }
        }
        result
    }

    pub fn tile_at(&self, x: i32, y: i32) -> Option<&Tile<T>> {
        for i in 0..self.chunks.len() {
            let chunk = &self.chunks[i];
            if (x > chunk.x) && (x < chunk.x + chunk.width as i32) &&
               (y > chunk.y) && (y < chunk.y + chunk.height as i32) {
                return chunk.tile_at(x, y);
            }
        }
        None
    }
}
<commit_msg>bug fix<commit_after>use chunk::Chunk;
use tile::Tile;
use std::collections::HashMap;

const DEF_CHUNK_WIDTH: i32 = 100;
const DEF_CHUNK_HEIGHT: i32 = 100;

pub struct TilesLayer<T> {
    x_offset: i32,
    y_offset: i32,
    chunks: Vec<Chunk<T>>,
}

impl<T> TilesLayer<T> {
    pub fn new() -> TilesLayer<T> {
        TilesLayer {
            x_offset: 0,
            y_offset: 0,
            chunks: Vec::<Chunk<T>>::new(),
        }
    }

    #[inline]
    fn get_rel_x(&self, x: i32) -> i32 {
        x - self.x_offset
    }

    #[inline]
    fn get_rel_y(&self, y: i32) -> i32 {
        y - self.y_offset
    }

    pub fn add_tile(&mut self, x: i32, y: i32, w: u32, h: u32, tile_info: T) {
        let mut chunk_ind: i32 = -1;
        let rel_x = self.get_rel_x(x);
        let rel_y = self.get_rel_y(y);
        for i in 0..self.chunks.len() {
            let chunk = &self.chunks[i];
            if (rel_x >= chunk.x) && (rel_x < chunk.x + chunk.width as i32) &&
               (rel_y >= chunk.y) && (rel_y < chunk.y + chunk.height as i32) {
                chunk_ind = i as i32;
                break;
            }
        }
        if chunk_ind < 0 {
            self.chunks.push(Chunk::new((rel_x/DEF_CHUNK_WIDTH)*DEF_CHUNK_WIDTH,
                                        (rel_y/DEF_CHUNK_HEIGHT)*DEF_CHUNK_HEIGHT,
                                        DEF_CHUNK_WIDTH as u32,
                                        DEF_CHUNK_HEIGHT as u32));
            chunk_ind = (self.chunks.len()-1) as i32;
        }
        self.chunks[chunk_ind as usize].add_tile(rel_x, rel_y, w, h, tile_info);
    }

    pub fn get_tiles(&self, cam_x: f64, cam_y: f64, cam_w: i32, cam_h: i32) -> HashMap<(i32, i32,), &Tile<T>> {
        let rel_x = self.get_rel_x(cam_x as i32);
        let rel_y = self.get_rel_y(cam_y as i32);
        let mut result = HashMap::<(i32, i32), &Tile<T>>::new();
        for chunk in self.chunks.iter() {
            if (rel_x + cam_w >= chunk.x) && (rel_x < chunk.x + chunk.width as i32) &&
               (rel_y + cam_h >= chunk.y) && (rel_y < chunk.y + chunk.height as i32) {
                chunk.get_tiles(&mut result);
            }
        }
        result
    }

    pub fn tile_at(&self, x: i32, y: i32) -> Option<&Tile<T>> {
        for i in 0..self.chunks.len() {
            let chunk = &self.chunks[i];
            if (x >= chunk.x) && (x < chunk.x + chunk.width as i32) &&
               (y >= chunk.y) && (y < chunk.y + chunk.height as i32) {
                return chunk.tile_at(x, y);
            }
        }
        None
    }
}
<|endoftext|>


<commit_before>use crate::buf::Buf;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::fs;
use substring::Substring;

#[derive(Serialize, Deserialize, Debug)]
pub struct Token {
    pub kind: String,
    pub content: Option<String>,
    pub pos: String,
}

impl fmt::Display for Token {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.content.is_none() {
            return write!(f, "[{}]", self.kind);
        }
        let c = self.content.as_ref().unwrap().substring(0, 40);
        return write!(f, "[{} {}]", self.kind, c);
    }
}

const SPACES: &str = "\r\n\t ";

pub fn read_token(buf: &mut Buf) -> Option<Token> {
    buf.read_set(SPACES.to_string());
    if buf.ended() {
        return None;
    }

    let pos = buf.pos();

    if buf.skip_literal("#import") {
        buf.read_set(SPACES.to_string());
        return Some(Token {
            kind: "import".to_string(),
            content: Some(buf.skip_until('\n').trim().to_string()),
            pos,
        });
    }

    if buf.peek().unwrap() == '#' {
        return Some(Token {
            kind: "macro".to_string(),
            content: Some(buf.skip_until('\n')),
            pos,
        });
    }

    if buf.literal_follows("/*") {
        return Some(read_multiline_comment(buf));
    }

    if buf.skip_literal("//") {
        return Some(Token {
            kind: "comment".to_string(),
            content: Some(buf.skip_until('\n')),
            pos,
        });
    }

    let next = buf.peek().unwrap();
    if next.is_ascii_alphabetic() || next == '_' {
        return Some(read_word(buf));
    }

    if next.is_ascii_digit() {
        return Some(read_number(buf));
    }

    if next == '"' {
        return Some(read_string_literal(buf));
    }

    if next == '\'' {
        return Some(read_char_literal(buf));
    }

    // Sorted by length, longest first.
    let symbols = [
        "<<=", ">>=", "...", "++", "--", "->", "<<", ">>", "<=", ">=", "&&", "||", "+=", "-=",
        "*=", "/=", "%=", "&=", "^=", "|=", "==", "!=", "!", "~", "&", "^", "*", "/", "%", "=",
        "|", ":", ",", "<", ">", "+", "-", "{", "}", ";", "[", "]", "(", ")", ".", "?",
    ];
    for sym in &symbols {
        if buf.skip_literal(sym) {
            return Some(Token {
                kind: sym.to_string(),
                content: None,
                pos,
            });
        }
    }

    return Some(Token {
        kind: "error".to_string(),
        content: Some(format!("Unexpected character: '{}'", next).to_string()),
        pos,
    });
}

fn read_number(buf: &mut Buf) -> Token {
    if buf.literal_follows("0x") {
        return read_hex(buf);
    }

    let pos = buf.pos();
    let alpha = "0123456789";
    let mut num = buf.read_set(alpha.to_string());

    let mut modifiers = String::from("UL");

    if buf.more() && buf.peek().unwrap() == '.' {
        modifiers += "f";
        num += &buf.get().unwrap().to_string();
        num += &buf.read_set(alpha.to_string());
    }

    num += &buf.read_set(modifiers);

    if buf.more() && buf.peek().unwrap().is_ascii_alphabetic() {
        let c = buf.peek().unwrap();
        return Token {
            kind: "error".to_string(),
            content: Some(format!("Unexpected character: '{}'", c)),
            pos: buf.pos(),
        };
    }
    return Token {
        kind: "num".to_string(),
        content: Some(num),
        pos,
    };
}

fn read_hex(buf: &mut Buf) -> Token {
    let pos = buf.pos();

    // Skip "0x"
    buf.get();
    buf.get();

    let num = buf.read_set("0123456789ABCDEFabcdef".to_string()) + &buf.read_set("UL".to_string());

    return Token {
        kind: "num".to_string(),
        content: Some(String::from("0x") + &num),
        pos,
    };
}

fn read_string_literal(buf: &mut Buf) -> Token {
    let pos = buf.pos();
    let mut s = String::new();
    // A string literal may be split into parts.
    while buf.more() && buf.peek().unwrap() == '"' {
        buf.get();
        let mut substr = String::new();
        while buf.more() && buf.peek().unwrap() != '"' {
            let ch = buf.get().unwrap();
            substr += &ch.to_string();
            if ch == '\\' {
                substr += &buf.get().unwrap().to_string();
            }
        }
        if !buf.more() || buf.get().unwrap() != '"' {
            return Token {
                kind: "error".to_string(),
                content: Some("Double quote expected".to_string()),
                pos,
            };
        }
        s += &substr;
        buf.read_set(SPACES.to_string());
    }
    return Token {
        kind: "string".to_string(),
        content: Some(s),
        pos,
    };
}

fn read_word(buf: &mut Buf) -> Token {
    let pos = buf.pos();
    let mut word = String::new();
    while buf.more() {
        let ch = buf.peek().unwrap();
        if !ch.is_alphanumeric() && ch != '_' {
            break;
        }
        word.push(buf.get().unwrap());
    }

    let keywords = [
        "default", "typedef", "struct", "union", "const", "return", "switch", "sizeof", "while",
        "case", "enum", "else", "for", "pub", "if",
    ];

    if keywords.contains(&word.as_str()) {
        return Token {
            kind: word,
            content: None,
            pos,
        };
    }
    return Token {
        kind: "word".to_string(),
        content: Some(word),
        pos,
    };
}

fn read_char_literal(buf: &mut Buf) -> Token {
    let pos = buf.pos();
    buf.get();

    let mut s = String::new();
    if buf.more() && buf.peek().unwrap() == '\\' {
        s.push(buf.get().unwrap());
    }

    s.push(buf.get().unwrap());
    if buf.get().unwrap() != '\'' {
        return Token {
            kind: "error".to_string(),
            content: Some("Single quote expected".to_string()),
            pos,
        };
    }
    return Token {
        kind: "char".to_string(),
        content: Some(s),
        pos,
    };
}

fn read_multiline_comment(buf: &mut Buf) -> Token {
    let pos = buf.pos();
    buf.skip_literal("/*");
    let comment = buf.until_literal("*/");
    if !buf.skip_literal("*/") {
        return Token {
            kind: "error".to_string(),
            content: Some("*/ expected".to_string()),
            pos,
        };
    }
    return Token {
        kind: "comment".to_string(),
        content: Some(comment),
        pos,
    };
}

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

    fn _read_token(s: &str) -> Token {
        let mut b = crate::buf::new(s.to_string());
        return read_token(&mut b).unwrap();
    }

    #[test]
    fn read_token_test() {
        struct C<'a> {
            input: &'a str,
            kind: &'a str,
            content: &'a str,
            pos: &'a str,
        }
        let cases = [
            C {
                input: "#type abc\n",
                kind: "macro",
                content: "#type abc",
                pos: "1:1",
            },
            C {
                input: "/* \ncomment /* comment \n*/ 123",
                kind: "comment",
                content: " \ncomment /* comment \n",
                pos: "1:1",
            },
            C {
                input: "// comment\n123",
                kind: "comment",
                content: " comment",
                pos: "1:1",
            },
            C {
                input: "abc_123++",
                kind: "word",
                content: "abc_123",
                pos: "1:1",
            },
            C {
                input: "'a'123",
                kind: "char",
                content: "a",
                pos: "1:1",
            },
            C {
                input: "'\\t'123",
                kind: "char",
                content: "\\t",
                pos: "1:1",
            },
            C {
                input: "0x123 abc",
                kind: "num",
                content: "0x123",
                pos: "1:1",
            },
            C {
                input: "123 abc",
                kind: "num",
                content: "123",
                pos: "1:1",
            },
            C {
                input: "123UL abc",
                kind: "num",
                content: "123UL",
                pos: "1:1",
            },
            C {
                input: "123.45 abc",
                kind: "num",
                content: "123.45",
                pos: "1:1",
            },
            C {
                input: "0x123",
                kind: "num",
                content: "0x123",
                pos: "1:1",
            },
            C {
                input: "0x123UL",
                kind: "num",
                content: "0x123UL",
                pos: "1:1",
            },
            C {
                input: "\"abc\" 123",
                kind: "string",
                content: "abc",
                pos: "1:1",
            },
            C {
                input: "\"ab\\\"c\" 123",
                kind: "string",
                content: "ab\\\"c",
                pos: "1:1",
            },
            C {
                input: "\"abc\" \"def\" 123",
                kind: "string",
                content: "abcdef",
                pos: "1:1",
            },
        ];

        for case in &cases {
            let t = _read_token(case.input);
            assert_eq!(t.content.unwrap(), case.content);
            assert_eq!(t.kind, case.kind);
            assert_eq!(t.pos, case.pos);
        }

        let symbols = [
            "<<=", ">>=", "...", "++", "--", "->", "<<", ">>", "<=", ">=", "&&", "||", "+=", "-=",
            "*=", "/=", "%=", "&=", "^=", "|=", "==", "!=", "!", "~", "&", "^", "*", "/", "%", "=",
            "|", ":", ",", "<", ">", "+", "-", "{", "}", ";", "[", "]", "(", ")", ".", "?",
        ];
        for sym in &symbols {
            let t = _read_token(format!("{}123", sym).as_str());
            assert_eq!(t.content.is_none(), true);
            assert_eq!(t.kind, sym.to_string());
            assert_eq!(t.pos, "1:1");
        }

        let keywords = [
            "default", "typedef", "struct", "union", "const", "return", "switch", "sizeof",
            "while", "case", "enum", "else", "for", "pub", "if",
        ];
        for kw in &keywords {
            let t = _read_token(format!("{} 123", kw).as_str());
            assert_eq!(t.content.is_none(), true);
            assert_eq!(t.kind, kw.to_string());
            assert_eq!(t.pos, "1:1");
        }
    }
}

pub struct Lexer {
    toks: Vec<Token>,
}

pub fn for_file(filename: &str) -> Result<Lexer, String> {
    let contents = fs::read_to_string(filename).expect("Something went wrong reading the file");
    return for_string(contents);
}

pub fn for_string(contents: String) -> Result<Lexer, String> {
    let mut toks: Vec<Token> = Vec::new();
    let mut b = crate::buf::new(contents);
    loop {
        let r = read_token(&mut b);
        if r.is_none() {
            break;
        }
        let tok = r.unwrap();
        if tok.kind == "error" {
            let err = format!("{} at {}", tok.content.unwrap(), tok.pos);
            return Err(err);
        }
        toks.push(tok)
    }
    toks.reverse();
    return Ok(Lexer { toks });
}

impl Lexer {
    pub fn ended(&mut self) -> bool {
        return !self.more();
    }

    pub fn more(&mut self) -> bool {
        let r = self.get();
        if r.is_none() {
            return false;
        }
        self.unget(r.unwrap());
        return true;
    }

    pub fn get(&mut self) -> Option<Token> {
        loop {
            if self.toks.len() == 0 {
                return None;
            }
            let tok = self.toks.pop().unwrap();
            if tok.kind != "comment" {
                return Some(tok);
            }
        }
    }

    pub fn unget(&mut self, t: Token) {
        self.toks.push(t);
    }
    pub fn peek(&self) -> Option<&Token> {
        return self.peek_n(0);
    }

    pub fn peek_skipping_comments(&self) -> Option<&Token> {
        let mut n: usize = 0;
        loop {
            let r = self.peek_n(n);
            if r.is_none() {
                return None;
            }
            if r.unwrap().kind == "comment" {
                n += 1;
                continue;
            }
            return r;
        }
    }

    pub fn peek_n(&self, n: usize) -> Option<&Token> {
        let l = self.toks.len();
        if l <= n {
            return None;
        }
        let tok = &self.toks[l - 1 - n];
        return Some(tok);
    }
    pub fn follows(&mut self, token_type: &str) -> bool {
        return self.more() && self.peek().unwrap().kind == token_type;
    }
    pub fn eat(&mut self, token_type: &str) -> bool {
        if self.follows(token_type) {
            self.get();
            return true;
        }
        return false;
    }
}
<commit_msg>Add support for 1e6 literals<commit_after>use crate::buf::Buf;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::fs;
use substring::Substring;

#[derive(Serialize, Deserialize, Debug)]
pub struct Token {
    pub kind: String,
    pub content: Option<String>,
    pub pos: String,
}

impl fmt::Display for Token {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.content.is_none() {
            return write!(f, "[{}]", self.kind);
        }
        let c = self.content.as_ref().unwrap().substring(0, 40);
        return write!(f, "[{} {}]", self.kind, c);
    }
}

const SPACES: &str = "\r\n\t ";

pub fn read_token(buf: &mut Buf) -> Option<Token> {
    buf.read_set(SPACES.to_string());
    if buf.ended() {
        return None;
    }

    let pos = buf.pos();

    if buf.skip_literal("#import") {
        buf.read_set(SPACES.to_string());
        return Some(Token {
            kind: "import".to_string(),
            content: Some(buf.skip_until('\n').trim().to_string()),
            pos,
        });
    }

    if buf.peek().unwrap() == '#' {
        return Some(Token {
            kind: "macro".to_string(),
            content: Some(buf.skip_until('\n')),
            pos,
        });
    }

    if buf.literal_follows("/*") {
        return Some(read_multiline_comment(buf));
    }

    if buf.skip_literal("//") {
        return Some(Token {
            kind: "comment".to_string(),
            content: Some(buf.skip_until('\n')),
            pos,
        });
    }

    let next = buf.peek().unwrap();
    if next.is_ascii_alphabetic() || next == '_' {
        return Some(read_word(buf));
    }

    if next.is_ascii_digit() {
        return Some(read_number(buf));
    }

    if next == '"' {
        return Some(read_string_literal(buf));
    }

    if next == '\'' {
        return Some(read_char_literal(buf));
    }

    // Sorted by length, longest first.
    let symbols = [
        "<<=", ">>=", "...", "++", "--", "->", "<<", ">>", "<=", ">=", "&&", "||", "+=", "-=",
        "*=", "/=", "%=", "&=", "^=", "|=", "==", "!=", "!", "~", "&", "^", "*", "/", "%", "=",
        "|", ":", ",", "<", ">", "+", "-", "{", "}", ";", "[", "]", "(", ")", ".", "?",
    ];
    for sym in &symbols {
        if buf.skip_literal(sym) {
            return Some(Token {
                kind: sym.to_string(),
                content: None,
                pos,
            });
        }
    }

    return Some(Token {
        kind: "error".to_string(),
        content: Some(format!("Unexpected character: '{}'", next).to_string()),
        pos,
    });
}

fn read_number(buf: &mut Buf) -> Token {
    if buf.literal_follows("0x") {
        return read_hex(buf);
    }

    let pos = buf.pos();
    let digits = "0123456789";
    let mut modifiers = String::from("UL");
    let mut num = buf.read_set(digits.to_string());

    if buf.more() && buf.peek().unwrap() == '.' {
        modifiers += "f";
        num += &buf.get().unwrap().to_string();
        num += &buf.read_set(digits.to_string());
    }

    if buf.more() && (buf.peek().unwrap() == 'e' || buf.peek().unwrap() == 'E') {
        num += &buf.get().unwrap().to_string();
        if buf.peek().unwrap() == '-' {
            num += &buf.get().unwrap().to_string();
        }
        num += &buf.read_set(digits.to_string());
    }

    num += &buf.read_set(modifiers);

    if buf.more() && buf.peek().unwrap().is_ascii_alphabetic() {
        let c = buf.peek().unwrap();
        return Token {
            kind: "error".to_string(),
            content: Some(format!("Unexpected character: '{}'", c)),
            pos: buf.pos(),
        };
    }
    return Token {
        kind: "num".to_string(),
        content: Some(num),
        pos,
    };
}

fn read_hex(buf: &mut Buf) -> Token {
    let pos = buf.pos();

    // Skip "0x"
    buf.get();
    buf.get();

    let num = buf.read_set("0123456789ABCDEFabcdef".to_string()) + &buf.read_set("UL".to_string());

    return Token {
        kind: "num".to_string(),
        content: Some(String::from("0x") + &num),
        pos,
    };
}

fn read_string_literal(buf: &mut Buf) -> Token {
    let pos = buf.pos();
    let mut s = String::new();
    // A string literal may be split into parts.
    while buf.more() && buf.peek().unwrap() == '"' {
        buf.get();
        let mut substr = String::new();
        while buf.more() && buf.peek().unwrap() != '"' {
            let ch = buf.get().unwrap();
            substr += &ch.to_string();
            if ch == '\\' {
                substr += &buf.get().unwrap().to_string();
            }
        }
        if !buf.more() || buf.get().unwrap() != '"' {
            return Token {
                kind: "error".to_string(),
                content: Some("Double quote expected".to_string()),
                pos,
            };
        }
        s += &substr;
        buf.read_set(SPACES.to_string());
    }
    return Token {
        kind: "string".to_string(),
        content: Some(s),
        pos,
    };
}

fn read_word(buf: &mut Buf) -> Token {
    let pos = buf.pos();
    let mut word = String::new();
    while buf.more() {
        let ch = buf.peek().unwrap();
        if !ch.is_alphanumeric() && ch != '_' {
            break;
        }
        word.push(buf.get().unwrap());
    }

    let keywords = [
        "default", "typedef", "struct", "union", "const", "return", "switch", "sizeof", "while",
        "case", "enum", "else", "for", "pub", "if",
    ];

    if keywords.contains(&word.as_str()) {
        return Token {
            kind: word,
            content: None,
            pos,
        };
    }
    return Token {
        kind: "word".to_string(),
        content: Some(word),
        pos,
    };
}

fn read_char_literal(buf: &mut Buf) -> Token {
    let pos = buf.pos();
    buf.get();

    let mut s = String::new();
    if buf.more() && buf.peek().unwrap() == '\\' {
        s.push(buf.get().unwrap());
    }

    s.push(buf.get().unwrap());
    if buf.get().unwrap() != '\'' {
        return Token {
            kind: "error".to_string(),
            content: Some("Single quote expected".to_string()),
            pos,
        };
    }
    return Token {
        kind: "char".to_string(),
        content: Some(s),
        pos,
    };
}

fn read_multiline_comment(buf: &mut Buf) -> Token {
    let pos = buf.pos();
    buf.skip_literal("/*");
    let comment = buf.until_literal("*/");
    if !buf.skip_literal("*/") {
        return Token {
            kind: "error".to_string(),
            content: Some("*/ expected".to_string()),
            pos,
        };
    }
    return Token {
        kind: "comment".to_string(),
        content: Some(comment),
        pos,
    };
}

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

    fn _read_token(s: &str) -> Token {
        let mut b = crate::buf::new(s.to_string());
        return read_token(&mut b).unwrap();
    }

    #[test]
    fn read_token_test() {
        struct C<'a> {
            input: &'a str,
            kind: &'a str,
            content: &'a str,
            pos: &'a str,
        }
        let cases = [
            C {
                input: "#type abc\n",
                kind: "macro",
                content: "#type abc",
                pos: "1:1",
            },
            C {
                input: "/* \ncomment /* comment \n*/ 123",
                kind: "comment",
                content: " \ncomment /* comment \n",
                pos: "1:1",
            },
            C {
                input: "// comment\n123",
                kind: "comment",
                content: " comment",
                pos: "1:1",
            },
            C {
                input: "abc_123++",
                kind: "word",
                content: "abc_123",
                pos: "1:1",
            },
            C {
                input: "'a'123",
                kind: "char",
                content: "a",
                pos: "1:1",
            },
            C {
                input: "'\\t'123",
                kind: "char",
                content: "\\t",
                pos: "1:1",
            },
            C {
                input: "0x123 abc",
                kind: "num",
                content: "0x123",
                pos: "1:1",
            },
            C {
                input: "123 abc",
                kind: "num",
                content: "123",
                pos: "1:1",
            },
            C {
                input: "123UL abc",
                kind: "num",
                content: "123UL",
                pos: "1:1",
            },
            C {
                input: "123.45 abc",
                kind: "num",
                content: "123.45",
                pos: "1:1",
            },
            C {
                input: "0x123",
                kind: "num",
                content: "0x123",
                pos: "1:1",
            },
            C {
                input: "0x123UL",
                kind: "num",
                content: "0x123UL",
                pos: "1:1",
            },
            C {
                input: "\"abc\" 123",
                kind: "string",
                content: "abc",
                pos: "1:1",
            },
            C {
                input: "\"ab\\\"c\" 123",
                kind: "string",
                content: "ab\\\"c",
                pos: "1:1",
            },
            C {
                input: "\"abc\" \"def\" 123",
                kind: "string",
                content: "abcdef",
                pos: "1:1",
            },
            C {
                input: "1e6",
                kind: "num",
                content: "1e6",
                pos: "1:1",
            },
            C {
                input: "3.917609E-2",
                kind: "num",
                content: "3.917609E-2",
                pos: "1:1",
            },
        ];

        for case in &cases {
            let t = _read_token(case.input);
            assert_eq!(t.content.unwrap(), case.content);
            assert_eq!(t.kind, case.kind);
            assert_eq!(t.pos, case.pos);
        }

        let symbols = [
            "<<=", ">>=", "...", "++", "--", "->", "<<", ">>", "<=", ">=", "&&", "||", "+=", "-=",
            "*=", "/=", "%=", "&=", "^=", "|=", "==", "!=", "!", "~", "&", "^", "*", "/", "%", "=",
            "|", ":", ",", "<", ">", "+", "-", "{", "}", ";", "[", "]", "(", ")", ".", "?",
        ];
        for sym in &symbols {
            let t = _read_token(format!("{}123", sym).as_str());
            assert_eq!(t.content.is_none(), true);
            assert_eq!(t.kind, sym.to_string());
            assert_eq!(t.pos, "1:1");
        }

        let keywords = [
            "default", "typedef", "struct", "union", "const", "return", "switch", "sizeof",
            "while", "case", "enum", "else", "for", "pub", "if",
        ];
        for kw in &keywords {
            let t = _read_token(format!("{} 123", kw).as_str());
            assert_eq!(t.content.is_none(), true);
            assert_eq!(t.kind, kw.to_string());
            assert_eq!(t.pos, "1:1");
        }
    }
}

pub struct Lexer {
    toks: Vec<Token>,
}

pub fn for_file(filename: &str) -> Result<Lexer, String> {
    let contents = fs::read_to_string(filename).expect("Something went wrong reading the file");
    return for_string(contents);
}

pub fn for_string(contents: String) -> Result<Lexer, String> {
    let mut toks: Vec<Token> = Vec::new();
    let mut b = crate::buf::new(contents);
    loop {
        let r = read_token(&mut b);
        if r.is_none() {
            break;
        }
        let tok = r.unwrap();
        if tok.kind == "error" {
            let err = format!("{} at {}", tok.content.unwrap(), tok.pos);
            return Err(err);
        }
        toks.push(tok)
    }
    toks.reverse();
    return Ok(Lexer { toks });
}

impl Lexer {
    pub fn ended(&mut self) -> bool {
        return !self.more();
    }

    pub fn more(&mut self) -> bool {
        let r = self.get();
        if r.is_none() {
            return false;
        }
        self.unget(r.unwrap());
        return true;
    }

    pub fn get(&mut self) -> Option<Token> {
        loop {
            if self.toks.len() == 0 {
                return None;
            }
            let tok = self.toks.pop().unwrap();
            if tok.kind != "comment" {
                return Some(tok);
            }
        }
    }

    pub fn unget(&mut self, t: Token) {
        self.toks.push(t);
    }
    pub fn peek(&self) -> Option<&Token> {
        return self.peek_n(0);
    }

    pub fn peek_skipping_comments(&self) -> Option<&Token> {
        let mut n: usize = 0;
        loop {
            let r = self.peek_n(n);
            if r.is_none() {
                return None;
            }
            if r.unwrap().kind == "comment" {
                n += 1;
                continue;
            }
            return r;
        }
    }

    pub fn peek_n(&self, n: usize) -> Option<&Token> {
        let l = self.toks.len();
        if l <= n {
            return None;
        }
        let tok = &self.toks[l - 1 - n];
        return Some(tok);
    }
    pub fn follows(&mut self, token_type: &str) -> bool {
        return self.more() && self.peek().unwrap().kind == token_type;
    }
    pub fn eat(&mut self, token_type: &str) -> bool {
        if self.follows(token_type) {
            self.get();
            return true;
        }
        return false;
    }
}
<|endoftext|>