feat: string parsers developed for all formats with strict regex
NOTE: this will be diluted down in order to admit any type of weird string
This commit is contained in:
45
colorizer/Cargo.lock
generated
45
colorizer/Cargo.lock
generated
@@ -2,6 +2,15 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
version = "0.1.6"
|
||||
@@ -35,6 +44,7 @@ name = "colorizer"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clipboard",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -58,6 +68,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
@@ -87,6 +103,35 @@ dependencies = [
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
||||
@@ -5,3 +5,4 @@ edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
clipboard = "0.5.0"
|
||||
regex = "1.11.1"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::color::{ColorHue, HSL, Percentage, RGB};
|
||||
use regex::Regex;
|
||||
|
||||
impl HSL {
|
||||
pub fn new(h: u16, s: u8, l: u8) -> Self {
|
||||
@@ -20,6 +21,28 @@ impl PartialEq for HSL {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: manage error
|
||||
impl From<String> for HSL {
|
||||
fn from(value: String) -> Self {
|
||||
let regex = Regex::new(r"hsl\(([0-9]+),([0-9]+),([0-9 ]+)\)").unwrap();
|
||||
let numbers = value.replace(" ", "").replace("%", "");
|
||||
let result = regex.captures(&numbers);
|
||||
|
||||
match result {
|
||||
Some(value_list) => {
|
||||
// Numeric
|
||||
let h: u16 = value_list[1].parse::<u16>().unwrap();
|
||||
let s: u8 = value_list[2].parse::<u8>().unwrap();
|
||||
let l: u8 = value_list[3].parse::<u8>().unwrap();
|
||||
return Self::new(h, s, l);
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
|
||||
Self::new(0, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RGB> for HSL {
|
||||
fn from(value: RGB) -> Self {
|
||||
let r = value.0.to_f32() / 255.0;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use regex::Regex;
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::color::{ColorHue, HSV, Percentage, RGB};
|
||||
@@ -28,6 +29,28 @@ impl PartialEq for HSV {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: manage error
|
||||
impl From<String> for HSV {
|
||||
fn from(value: String) -> Self {
|
||||
let regex = Regex::new(r"hsv\(([0-9]+),([0-9]+),([0-9 ]+)\)").unwrap();
|
||||
let numbers = value.replace(" ", "").replace("%", "");
|
||||
let result = regex.captures(&numbers);
|
||||
|
||||
match result {
|
||||
Some(value_list) => {
|
||||
// Numeric
|
||||
let h: u16 = value_list[1].parse::<u16>().unwrap();
|
||||
let s: u8 = value_list[2].parse::<u8>().unwrap();
|
||||
let v: u8 = value_list[3].parse::<u8>().unwrap();
|
||||
return Self::new(h, s, v);
|
||||
}
|
||||
None => (),
|
||||
}
|
||||
|
||||
Self::new(0, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RGB> for HSV {
|
||||
fn from(color: RGB) -> Self {
|
||||
let r = color.0.to_f32() / 255.0;
|
||||
|
||||
@@ -8,6 +8,8 @@ pub mod rgb;
|
||||
|
||||
use std::fmt::UpperHex;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
use crate::core::ranged::RangedInt;
|
||||
|
||||
pub type ColorIntensity = RangedInt<0, 255>;
|
||||
@@ -22,7 +24,47 @@ pub struct HSV(ColorHue, Percentage, Percentage);
|
||||
#[derive(Debug)]
|
||||
pub struct Color(RGB);
|
||||
|
||||
impl Color {}
|
||||
impl Color {
|
||||
pub fn try_parse(input: String) -> Result<Color, ()> {
|
||||
let input = input.replace(" ", "").to_uppercase();
|
||||
|
||||
let hex_regex = Regex::new(r".*(#[a-fA-F0-9]{3,6}).*").unwrap();
|
||||
let rgb_regex =
|
||||
Regex::new(r"(rgb\([ ]*[0-9]+[ ]*,[ ]*[0-9]+[ ]*,[ ]*[0-9 ]+[ ]*\)).*").unwrap();
|
||||
let hsl_regex =
|
||||
Regex::new(r"(hsl\([ ]*[0-9]+[ ]*,[0-9]+[ ]*[%]*[ ]*,[0-9 ]+[ ]*[%]*[ ]*\)).*")
|
||||
.unwrap();
|
||||
let hsv_regex =
|
||||
Regex::new(r"(hsv\([ ]*[0-9]+[ ]*,[0-9]+[ ]*[%]*[ ]*,[0-9 ]+[ ]*[%]*[ ]*\)).*")
|
||||
.unwrap();
|
||||
|
||||
let hex_result = hex_regex.captures(&input);
|
||||
match hex_result {
|
||||
Some(color) => return Ok(Color::from(RGB::from(color[1].to_string()))),
|
||||
None => (),
|
||||
}
|
||||
|
||||
let rgb_result = rgb_regex.captures(&input);
|
||||
match rgb_result {
|
||||
Some(color) => return Ok(Color::from(RGB::from(color[1].to_string()))),
|
||||
None => (),
|
||||
}
|
||||
|
||||
let hsl_result = hsl_regex.captures(&input);
|
||||
match hsl_result {
|
||||
Some(color) => return Ok(Color::from(HSL::from(color[1].to_string()))),
|
||||
None => (),
|
||||
}
|
||||
|
||||
let hsv_result = hsv_regex.captures(&input);
|
||||
match hsv_result {
|
||||
Some(color) => return Ok(Color::from(HSV::from(color[1].to_string()))),
|
||||
None => (),
|
||||
}
|
||||
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
impl UpperHex for Color {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use regex::Regex;
|
||||
use std::fmt::{Display, UpperHex};
|
||||
|
||||
use crate::{
|
||||
@@ -15,6 +16,39 @@ impl RGB {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: manage error
|
||||
impl From<String> for RGB {
|
||||
fn from(value: String) -> Self {
|
||||
let regex = Regex::new(r"rgb\(([0-9]+),([0-9]+),([0-9 ]+)\)").unwrap();
|
||||
let mut numbers = value.replace(" ", "");
|
||||
let result = regex.captures(&numbers);
|
||||
|
||||
match result {
|
||||
Some(value_list) => {
|
||||
// Numeric
|
||||
let r: u8 = value_list[1].parse::<u8>().unwrap();
|
||||
let g: u8 = value_list[2].parse::<u8>().unwrap();
|
||||
let b: u8 = value_list[3].parse::<u8>().unwrap();
|
||||
return Self::new(r, g, b);
|
||||
}
|
||||
None => {
|
||||
// Hex
|
||||
if numbers.len() == 7 {
|
||||
numbers.remove(0);
|
||||
let hex = numbers.split_at(2);
|
||||
let r = u8::from_str_radix(hex.0, 16).unwrap();
|
||||
let hex = hex.1.split_at(2);
|
||||
let g = u8::from_str_radix(hex.0, 16).unwrap();
|
||||
let b = u8::from_str_radix(hex.1, 16).unwrap();
|
||||
return Self::new(r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Self::new(0, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for RGB {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0 == other.0 && self.1 == other.1 && self.2 == other.2
|
||||
|
||||
@@ -162,4 +162,93 @@ pub mod tests {
|
||||
let color = HSV::new(142, 92, 94);
|
||||
assert_eq!(RGB::from(color), RGB::new(19, 240, 100));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rgb_string_parse() {
|
||||
// Base colors
|
||||
// HEX
|
||||
let color = "#FF0000";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(255, 0, 0));
|
||||
let color = "#00FF00";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(0, 255, 0));
|
||||
let color = "#0000FF";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(0, 0, 255));
|
||||
// RGB
|
||||
let color = "rgb(255 ,0,0)";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(255, 0, 0));
|
||||
let color = "rgb(0,255, 0)";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(0, 255, 0));
|
||||
let color = "rgb(0 , 0, 255)";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(0, 0, 255));
|
||||
|
||||
// Complex colors
|
||||
// HEX
|
||||
let color = "#Ffb703";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(255, 183, 3));
|
||||
let color = "#588157";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(88, 129, 87));
|
||||
let color = "#fB8500";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(251, 133, 0));
|
||||
let color = "#8338eC";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(131, 56, 236));
|
||||
let color = "#9D8189";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(157, 129, 137));
|
||||
// RGB
|
||||
let color = "rgb(255, 183, 3)";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(255, 183, 3));
|
||||
let color = "rgb(88, 129, 87)";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(88, 129, 87));
|
||||
let color = "rgb(251, 133, 0)";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(251, 133, 0));
|
||||
let color = "rgb(131, 56, 236)";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(131, 56, 236));
|
||||
let color = "rgb(157, 129, 137)";
|
||||
assert_eq!(RGB::from(color.to_string()), RGB::new(157, 129, 137));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hsl_string_parse() {
|
||||
// Base colors
|
||||
let color = "hsl(0, 100, 50)";
|
||||
assert_eq!(HSL::from(color.to_string()), HSL::new(0, 100, 50));
|
||||
let color = "hsl(120, 100, 50)";
|
||||
assert_eq!(HSL::from(color.to_string()), HSL::new(120, 100, 50));
|
||||
let color = "hsl(240, 100, 50)";
|
||||
assert_eq!(HSL::from(color.to_string()), HSL::new(240, 100, 50));
|
||||
|
||||
// Complex colors
|
||||
let color = "hsl(255 , 83, 3)";
|
||||
assert_eq!(HSL::from(color.to_string()), HSL::new(255, 83, 3));
|
||||
let color = "hsl(88 , 29,87)";
|
||||
assert_eq!(HSL::from(color.to_string()), HSL::new(88, 29, 87));
|
||||
let color = "hsl(251,33,0)";
|
||||
assert_eq!(HSL::from(color.to_string()), HSL::new(251, 33, 0));
|
||||
let color = "hsl(131,56,36)";
|
||||
assert_eq!(HSL::from(color.to_string()), HSL::new(131, 56, 36));
|
||||
let color = "hsl(157,29, 37 )";
|
||||
assert_eq!(HSL::from(color.to_string()), HSL::new(157, 29, 37));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hsv_string_parse() {
|
||||
// Base colors
|
||||
let color = "hsv(0, 100, 50)";
|
||||
assert_eq!(HSV::from(color.to_string()), HSV::new(0, 100, 50));
|
||||
let color = "hsv(120, 100, 50)";
|
||||
assert_eq!(HSV::from(color.to_string()), HSV::new(120, 100, 50));
|
||||
let color = "hsv(240, 100, 50)";
|
||||
assert_eq!(HSV::from(color.to_string()), HSV::new(240, 100, 50));
|
||||
|
||||
// Complex colors
|
||||
let color = "hsv(255 , 83, 3)";
|
||||
assert_eq!(HSV::from(color.to_string()), HSV::new(255, 83, 3));
|
||||
let color = "hsv(88 , 29,87)";
|
||||
assert_eq!(HSV::from(color.to_string()), HSV::new(88, 29, 87));
|
||||
let color = "hsv(251,33,0)";
|
||||
assert_eq!(HSV::from(color.to_string()), HSV::new(251, 33, 0));
|
||||
let color = "hsv(131,56,36)";
|
||||
assert_eq!(HSV::from(color.to_string()), HSV::new(131, 56, 36));
|
||||
let color = "hsv(157,29, 37 )";
|
||||
assert_eq!(HSV::from(color.to_string()), HSV::new(157, 29, 37));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use clipboard::ClipboardContext;
|
||||
use clipboard::ClipboardProvider;
|
||||
|
||||
use crate::color::Color;
|
||||
use crate::color::HSV;
|
||||
use crate::color::RGB;
|
||||
|
||||
@@ -20,4 +21,11 @@ fn main() {
|
||||
let color = RGB::new(220, 10, 50);
|
||||
let hsv_color = HSV::from(RGB::new(220, 10, 50));
|
||||
println!("RGB color: {}, HSV Color: {}", color, hsv_color);
|
||||
|
||||
Color::try_parse("#F2FA01".to_string());
|
||||
Color::try_parse("rgb(1, 3,4)".to_string());
|
||||
Color::try_parse("rgb(1,3 ,4)".to_string());
|
||||
Color::try_parse("rgb(1,F,4)".to_string());
|
||||
Color::try_parse("hsl(100,100%,40%)".to_string());
|
||||
Color::try_parse("hsl(100,100%,40)".to_string());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user