pounce 2.0.2

A mediocre (but trying its best) uci chess engine
Documentation
use std::borrow::Borrow;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use thiserror::Error;

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Limits {
    pub depth: Option<u8>,
    pub nodes: Option<u64>,
    pub wtime: Option<i32>,
    pub btime: Option<i32>,
    pub winc: Option<u32>,
    pub binc: Option<u32>,
    pub movestogo: Option<u32>,
    pub movetime: Option<i32>,
    pub infinite: bool,
}

#[derive(Debug, Error)]
pub enum LimitsParseError {
    #[error("Invalid limit: {0}")]
    InvalidTime(#[from] std::num::ParseIntError),
}

impl Limits {
    pub fn new() -> Self {
        Limits {
            depth: None,
            nodes: None,
            wtime: None,
            btime: None,
            winc: None,
            binc: None,
            movestogo: None,
            movetime: None,
            infinite: false,
        }
    }

    pub fn from_tokens<T>(tokens: &[T]) -> Result<Self, LimitsParseError>
    where
        T: AsRef<str> + Borrow<str>,
    {
        enum ParseStage {
            Pre,
            Depth,
            Nodes,
            WTime,
            BTime,
            WInc,
            BInc,
            Movestogo,
            Movetime,
        }

        let mut limits = Limits::new();
        let mut parse_stage = ParseStage::Pre;

        for token in tokens {
            match token.as_ref() {
                "depth" => {
                    parse_stage = ParseStage::Depth;
                }
                "nodes" => {
                    parse_stage = ParseStage::Nodes;
                }
                "wtime" => {
                    parse_stage = ParseStage::WTime;
                }
                "btime" => {
                    parse_stage = ParseStage::BTime;
                }
                "winc" => {
                    parse_stage = ParseStage::WInc;
                }
                "binc" => {
                    parse_stage = ParseStage::BInc;
                }
                "movestogo" => {
                    parse_stage = ParseStage::Movestogo;
                }
                "movetime" => {
                    parse_stage = ParseStage::Movetime;
                }
                "infinite" => {
                    limits.infinite = true;
                }
                _ => match parse_stage {
                    ParseStage::Depth => {
                        limits.depth = Some(token.as_ref().parse()?);
                    }
                    ParseStage::Nodes => {
                        limits.nodes = Some(token.as_ref().parse()?);
                    }
                    ParseStage::WTime => {
                        limits.wtime = Some(token.as_ref().parse()?);
                    }
                    ParseStage::BTime => {
                        limits.btime = Some(token.as_ref().parse()?);
                    }
                    ParseStage::WInc => {
                        limits.winc = Some(token.as_ref().parse()?);
                    }
                    ParseStage::BInc => {
                        limits.binc = Some(token.as_ref().parse()?);
                    }
                    ParseStage::Movestogo => {
                        limits.movestogo = Some(token.as_ref().parse()?);
                    }
                    ParseStage::Movetime => {
                        limits.movetime = Some(token.as_ref().parse()?);
                    }
                    _ => {}
                },
            }
        }

        Ok(limits)
    }
}

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