colors/
colors.rs

1use noa_parser::acceptor::Acceptor;
2use noa_parser::bytes::primitives::number::Number;
3use noa_parser::bytes::primitives::string::DataString;
4use noa_parser::bytes::token::Token;
5use noa_parser::errors::ParseError::UnexpectedToken;
6use noa_parser::errors::ParseResult;
7use noa_parser::recognizer::recognize;
8use noa_parser::scanner::Scanner;
9use noa_parser::visitor::Visitor;
10
11#[derive(Debug)]
12struct RgbColor(u8, u8, u8);
13#[derive(Debug)]
14struct HexColor(u8, u8, u8);
15struct TupleColor(u8, u8, u8);
16
17enum ColorInternal {
18    Rgb(RgbColor),
19    Hex(HexColor),
20    Tuple(TupleColor),
21}
22
23impl From<ColorInternal> for Color {
24    fn from(value: ColorInternal) -> Self {
25        match value {
26            ColorInternal::Rgb(rgb) => Color(rgb.0, rgb.1, rgb.2),
27            ColorInternal::Hex(hex) => Color(hex.0, hex.1, hex.2),
28            ColorInternal::Tuple(tuple) => Color(tuple.0, tuple.1, tuple.2),
29        }
30    }
31}
32
33impl<'a> Visitor<'a, u8> for TupleColor {
34    fn accept(scanner: &mut Scanner<u8>) -> ParseResult<Self> {
35        // recognize the rgb color start "("
36        recognize(Token::OpenParen, scanner)?;
37        // recognize the red number
38        let red = Number::accept(scanner)?.0;
39        // recognize the comma
40        recognize(Token::Comma, scanner)?;
41        recognize(Token::Whitespace, scanner)?;
42        // recognize the green number
43        let green = Number::accept(scanner)?.0;
44        // recognize the comma
45        recognize(Token::Comma, scanner)?;
46        recognize(Token::Whitespace, scanner)?;
47        // recognize the blue number
48        let blue = Number::accept(scanner)?.0;
49        // recognize the rgb color end ")"
50        recognize(Token::CloseParen, scanner)?;
51        Ok(TupleColor(red, green, blue))
52    }
53}
54
55impl<'a> Visitor<'a, u8> for RgbColor {
56    fn accept(scanner: &mut Scanner<u8>) -> ParseResult<Self> {
57        let prefix = DataString::<&str>::accept(scanner)?.0;
58
59        if prefix != "rgb" {
60            return Err(UnexpectedToken);
61        }
62
63        // recognize the rgb color start "("
64        recognize(Token::OpenParen, scanner)?;
65        // recognize the red number
66        let red = Number::accept(scanner)?.0;
67        // recognize the comma
68        recognize(Token::Comma, scanner)?;
69        recognize(Token::Whitespace, scanner)?;
70        // recognize the green number
71        let green = Number::accept(scanner)?.0;
72        // recognize the comma
73        recognize(Token::Comma, scanner)?;
74        recognize(Token::Whitespace, scanner)?;
75        // recognize the blue number
76        let blue = Number::accept(scanner)?.0;
77        // recognize the rgb color end ")"
78        recognize(Token::CloseParen, scanner)?;
79        Ok(RgbColor(red, green, blue))
80    }
81}
82
83impl<'a> Visitor<'a, u8> for HexColor {
84    fn accept(scanner: &mut Scanner<u8>) -> ParseResult<Self> {
85        recognize(Token::Sharp, scanner)?;
86        let content = DataString::<&str>::accept(scanner)?.0;
87        let (red, green, blue) = (
88            u8::from_str_radix(&content[0..2], 16)?,
89            u8::from_str_radix(&content[2..4], 16)?,
90            u8::from_str_radix(&content[4..6], 16)?,
91        );
92        Ok(HexColor(red, green, blue))
93    }
94}
95
96#[derive(Debug)]
97#[allow(dead_code)]
98pub struct Color(u8, u8, u8);
99
100impl<'a> Visitor<'a, u8> for Color {
101    fn accept(scanner: &mut Scanner<u8>) -> ParseResult<Self> {
102        let color = Acceptor::new(scanner)
103            .try_or(ColorInternal::Hex)?
104            .try_or(ColorInternal::Rgb)?
105            .try_or(ColorInternal::Tuple)?
106            .finish()
107            .ok_or(UnexpectedToken)?;
108        Ok(color.into())
109    }
110}
111
112fn main() {
113    let data = b"rgb(255, 0, 0)";
114    let mut scanner = Scanner::new(data);
115    let result = Color::accept(&mut scanner);
116    println!("{:?}", result);
117
118    let data = b"#ff0000";
119    let mut scanner = Scanner::new(data);
120    let result = Color::accept(&mut scanner);
121    println!("{:?}", result);
122
123    let data = b"(255, 0, 0)";
124    let mut scanner = Scanner::new(data);
125    let result = Color::accept(&mut scanner);
126    println!("{:?}", result);
127}