bitsy-parser 0.70.2

A parser and utilities for working with Bitsy game data
Documentation
use crate::Position;
use std::str::FromStr;
use std::error::Error;
use std::fmt;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Transition {
    None,
    FadeToWhite,
    FadeToBlack,
    Wave,
    Tunnel,
    SlideUp,
    SlideDown,
    SlideLeft,
    SlideRight,
}

impl From<&str> for Transition {
    #[inline]
    fn from(str: &str) -> Transition {
        match str {
            "fade_w" => Transition::FadeToWhite,
            "fade_b" => Transition::FadeToBlack,
            "wave" => Transition::Wave,
            "tunnel" => Transition::Tunnel,
            "slide_u" => Transition::SlideUp,
            "slide_d" => Transition::SlideDown,
            "slide_l" => Transition::SlideLeft,
            "slide_r" => Transition::SlideRight,
            _ => Transition::None,
        }
    }
}

impl ToString for Transition {
    #[inline]
    fn to_string(&self) -> String {
        match &self {
            Transition::FadeToWhite => " FX fade_w",
            Transition::FadeToBlack => " FX fade_b",
            Transition::Wave => " FX wave",
            Transition::Tunnel => " FX tunnel",
            Transition::SlideUp => " FX slide_u",
            Transition::SlideDown => " FX slide_d",
            Transition::SlideLeft => " FX slide_l",
            Transition::SlideRight => " FX slide_r",
            Transition::None => "",
        }
        .to_string()
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Exit {
    /// destination
    pub room_id: String,
    /// id
    pub position: Position,
    pub effect: Transition,
}

impl Error for Exit {}

impl FromStr for Exit {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut parts = s.split_whitespace();
        let room_id = parts.next().unwrap().to_string();
        let position = Position::from_str(parts.next().unwrap());

        if position.is_err() {
            return Err("Invalid position for exit".to_string());
        }

        let position = position.unwrap();

        let effect = if parts.next().is_some() {
            Transition::from(parts.next().unwrap())
        } else {
            Transition::None
        };

        Ok(Exit { room_id, position, effect })
    }
}

impl fmt::Display for Exit {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{} {}{}",
            self.room_id,
            self.position.to_string(),
            self.effect.to_string()
        )
    }
}

#[cfg(test)]
mod test {
    use crate::exit::{Transition, Exit};
    use crate::position::Position;
    use std::str::FromStr;

    #[test]
    fn test_exit_from_string() {
        assert_eq!(
            Exit::from_str("a 12,13").unwrap(),
            Exit {
                room_id: "a".to_string(),
                position: Position { x: 12, y: 13 },
                effect: Transition::None
            }
        );
    }

    #[test]
    fn test_exit_from_string_with_fx() {
        assert_eq!(
            Exit::from_str("a 12,13 FX slide_u").unwrap(),
            Exit {
                room_id: "a".to_string(),
                position: Position { x: 12, y: 13 },
                effect: Transition::SlideUp
            }
        );
    }

    #[test]
    fn test_exit_to_string() {
        assert_eq!(
            Exit {
                room_id: "8".to_string(),
                position: Position { x: 5, y: 6 },
                effect: Transition::None
            }.to_string(),
            "8 5,6".to_string()
        );
    }

    #[test]
    fn test_exit_to_string_with_fx() {
        assert_eq!(
            Exit {
                room_id: "8".to_string(),
                position: Position { x: 5, y: 6 },
                effect: Transition::FadeToWhite
            }.to_string(),
            "8 5,6 FX fade_w".to_string()
        );
    }
}