#![no_std] use winnow::Result; use winnow::ascii::dec_uint; use winnow::combinator::{alt, preceded, seq}; use winnow::error::ContextError; use winnow::prelude::*; pub enum AnsiiEscape { Color16(ColorPlace, Color16Type, u8), Color256(u8), ColorRGB(ColorPlace, u8, u8, u8), } pub enum ColorPlace { Foreground, Background, } pub enum Color16Type { Normal, Bold, Brigth, } fn parse_color16(input: &mut &str) -> Result { let (c, _) = preceded("[", seq!(dec_uint, "m")).parse_next(input)?; if c < 30 || c == 38 || c == 48 || c > 49 { Err(ContextError::new()) } else { Ok(AnsiiEscape::Color16( ColorPlace::Foreground, Color16Type::Normal, c, )) } } fn parse_color_rgb(input: &mut &str) -> Result { let (t, _, r, _, g, _, b, _) = preceded( "[", seq!( alt(("38", "48")), ";", dec_uint, ";", dec_uint, ";", dec_uint, "m" ), ) .parse_next(input)?; Ok(AnsiiEscape::ColorRGB( if t == "38" { ColorPlace::Foreground } else { ColorPlace::Background }, r, g, b, )) } pub fn parse_ansii(input: &mut &str) -> Result { alt((parse_color_rgb, parse_color16)).parse_next(input) }