Skip to content

Commit 521219b

Browse files
committed
Convert str2col into DType and const N
It's getting hectic. I'll want to mildly refactor the tests later.
1 parent 511b292 commit 521219b

File tree

2 files changed

+98
-55
lines changed

2 files changed

+98
-55
lines changed

src/lib.rs

+29-16
Original file line numberDiff line numberDiff line change
@@ -928,15 +928,18 @@ fn rm_paren<'a>(s: &'a str) -> &'a str {
928928
/// ```
929929
/// use colcon::{str2col, Space};
930930
///
931-
/// assert_eq!(str2col("0.2, 0.5, 0.6"), Some((Space::SRGB, [0.2, 0.5, 0.6])));
932-
/// assert_eq!(str2col("lch:50;20;120"), Some((Space::CIELCH, [50.0, 20.0, 120.0])));
933-
/// assert_eq!(str2col("oklab(0.2, 0.6, -0.5)"), Some((Space::OKLAB, [0.2, 0.6, -0.5])));
934-
/// assert_eq!(str2col("srgb 100% 50% 25%"), Some((Space::SRGB, [1.0, 0.5, 0.25])));
931+
/// assert_eq!(str2col("0.2, 0.5, 0.6"), Some((Space::SRGB, [0.2f32, 0.5, 0.6])));
932+
/// assert_eq!(str2col("lch:50;20;120"), Some((Space::CIELCH, [50.0f32, 20.0, 120.0])));
933+
/// assert_eq!(str2col("oklab(0.2, 0.6, -0.5)"), Some((Space::OKLAB, [0.2f32, 0.6, -0.5])));
934+
/// assert_eq!(str2col("srgb 100% 50% 25%"), Some((Space::SRGB, [1.0f32, 0.5, 0.25])));
935935
/// ```
936-
pub fn str2col(mut s: &str) -> Option<(Space, [f32; 3])> {
936+
pub fn str2col<T: DType, const N: usize>(mut s: &str) -> Option<(Space, [T; N])>
937+
where
938+
Channels<N>: ValidChannels,
939+
{
937940
s = rm_paren(s.trim());
938941
let mut space = Space::SRGB;
939-
let mut result = [f32::NAN; 3];
942+
let mut result = [f32::NAN; N];
940943

941944
// Return hex if valid
942945
if let Ok(irgb) = hex_to_irgb(s) {
@@ -959,19 +962,26 @@ pub fn str2col(mut s: &str) -> Option<(Space, [f32; 3])> {
959962
.filter(|s| !s.is_empty())
960963
.enumerate()
961964
{
962-
if n > 2 {
965+
if n > 3 {
963966
return None;
967+
} else if n >= result.len() {
968+
continue;
964969
} else if let Ok(value) = split.parse::<f32>() {
965970
result[n] = value;
966971
} else if split.ends_with('%') {
967-
if let Ok(value) = split[0..(split.len() - 1)].parse::<f32>() {
972+
if let Ok(percent) = split[0..(split.len() - 1)].parse::<f32>() {
973+
// alpha
974+
if n == 3 {
975+
result[n] = percent / 100.0;
976+
continue;
977+
}
968978
let (q0, q100) = (space.srgb_quant0()[n], space.srgb_quant100()[n]);
969979
if q0.is_finite() && q100.is_finite() {
970-
result[n] = value / 100.0 * (q100 - q0) + q0;
980+
result[n] = percent / 100.0 * (q100 - q0) + q0;
971981
} else if Space::UCS_POLAR.contains(&space) {
972-
result[n] = value / 100.0 * 360.0
982+
result[n] = percent / 100.0 * 360.0
973983
} else if space == Space::HSV {
974-
result[n] = value / 100.0
984+
result[n] = percent / 100.0
975985
} else {
976986
return None;
977987
}
@@ -982,8 +992,8 @@ pub fn str2col(mut s: &str) -> Option<(Space, [f32; 3])> {
982992
return None;
983993
}
984994
}
985-
if result.iter().all(|v| v.is_finite()) {
986-
Some((space, result))
995+
if result.iter().take(3).all(|v| v.is_finite()) {
996+
Some((space, result.map(|c| c.to_dt())))
987997
} else {
988998
None
989999
}
@@ -992,7 +1002,10 @@ pub fn str2col(mut s: &str) -> Option<(Space, [f32; 3])> {
9921002
/// Convert a string into a pixel of the requested Space.
9931003
///
9941004
/// Shorthand for str2col() -> convert_space()
995-
pub fn str2space(s: &str, to: Space) -> Option<[f32; 3]> {
1005+
pub fn str2space<T: DType, const N: usize>(s: &str, to: Space) -> Option<[T; N]>
1006+
where
1007+
Channels<N>: ValidChannels,
1008+
{
9961009
str2col(s).map(|(from, mut col)| {
9971010
convert_space(from, to, &mut col);
9981011
col
@@ -1192,11 +1205,11 @@ where
11921205
// ### BACKWARD ### {{{
11931206

11941207
/// Convert integer (0..255) RGB to floating (0.0..1.0) RGB.
1195-
pub fn irgb_to_srgb<const N: usize>(pixel: [u8; N]) -> [f32; N]
1208+
pub fn irgb_to_srgb<T: DType, const N: usize>(pixel: [u8; N]) -> [T; N]
11961209
where
11971210
Channels<N>: ValidChannels,
11981211
{
1199-
pixel.map(|c| c as f32 / 255.0)
1212+
pixel.map(|c| T::ff32(c as f32 / 255.0))
12001213
}
12011214

12021215
/// Create integer RGB set from hex string.

src/tests.rs

+69-39
Original file line numberDiff line numberDiff line change
@@ -223,15 +223,15 @@ fn irgb_to_alpha() {
223223

224224
#[test]
225225
fn irgb_from() {
226-
let mut srgb = irgb_to_srgb(IRGB);
226+
let mut srgb = irgb_to_srgb::<f32, 3>(IRGB);
227227
// Round decimal to hundredths
228228
srgb.iter_mut().for_each(|c| *c = (*c * 100.0).round() / 100.0);
229229
assert_eq!([0.2, 0.35, 0.95], srgb)
230230
}
231231

232232
#[test]
233233
fn irgb_from_alpha() {
234-
let mut srgb = irgb_to_srgb(IRGBA);
234+
let mut srgb = irgb_to_srgb::<f32, 4>(IRGBA);
235235
// Round decimal to hundredths
236236
srgb.iter_mut().for_each(|c| *c = (*c * 100.0).round() / 100.0);
237237
assert_eq!([0.2, 0.35, 0.95, 0.35], srgb)
@@ -583,100 +583,112 @@ fn space_strings() {
583583
// ### Str2Col ### {{{
584584
#[test]
585585
fn str2col_base() {
586-
assert_eq!(str2col("0.2, 0.5, 0.6"), Some((Space::SRGB, [0.2, 0.5, 0.6])))
586+
assert_eq!(str2col("0.2, 0.5, 0.6"), Some((Space::SRGB, [0.2f32, 0.5, 0.6])))
587587
}
588588

589589
#[test]
590590
fn str2col_base_tight() {
591-
assert_eq!(str2col("0.2,0.5,0.6"), Some((Space::SRGB, [0.2, 0.5, 0.6])))
591+
assert_eq!(str2col("0.2,0.5,0.6"), Some((Space::SRGB, [0.2f32, 0.5, 0.6])))
592592
}
593593

594594
#[test]
595595
fn str2col_base_lop() {
596-
assert_eq!(str2col("0.2,0.5, 0.6"), Some((Space::SRGB, [0.2, 0.5, 0.6])))
596+
assert_eq!(str2col("0.2,0.5, 0.6"), Some((Space::SRGB, [0.2f32, 0.5, 0.6])))
597597
}
598598

599599
#[test]
600600
fn str2col_base_bare() {
601-
assert_eq!(str2col("0.2 0.5 0.6"), Some((Space::SRGB, [0.2, 0.5, 0.6])))
601+
assert_eq!(str2col("0.2 0.5 0.6"), Some((Space::SRGB, [0.2f32, 0.5, 0.6])))
602602
}
603603

604604
#[test]
605605
fn str2col_base_bare_fat() {
606-
assert_eq!(str2col(" 0.2 0.5 0.6 "), Some((Space::SRGB, [0.2, 0.5, 0.6])))
606+
assert_eq!(str2col(" 0.2 0.5 0.6 "), Some((Space::SRGB, [0.2f32, 0.5, 0.6])))
607607
}
608608

609609
#[test]
610610
fn str2col_base_paren() {
611-
assert_eq!(str2col("(0.2 0.5 0.6)"), Some((Space::SRGB, [0.2, 0.5, 0.6])))
611+
assert_eq!(str2col("(0.2 0.5 0.6)"), Some((Space::SRGB, [0.2f32, 0.5, 0.6])))
612612
}
613613

614614
#[test]
615615
fn str2col_base_paren2() {
616-
assert_eq!(str2col("{ 0.2 : 0.5 : 0.6 }"), Some((Space::SRGB, [0.2, 0.5, 0.6])))
616+
assert_eq!(str2col("{ 0.2 : 0.5 : 0.6 }"), Some((Space::SRGB, [0.2f32, 0.5, 0.6])))
617617
}
618618

619619
#[test]
620620
fn str2col_base_none() {
621-
assert_eq!(str2col(" 0.2 0.5 f"), None)
621+
assert_eq!(str2col::<f32, 3>(" 0.2 0.5 f"), None)
622622
}
623623

624624
#[test]
625625
fn str2col_base_none2() {
626-
assert_eq!(str2col("0.2*0.5 0.6"), None)
626+
assert_eq!(str2col::<f32, 3>("0.2*0.5 0.6"), None)
627627
}
628628

629629
#[test]
630630
fn str2col_base_paren_none() {
631-
assert_eq!(str2col("(0.2 0.5 0.6"), None)
631+
assert_eq!(str2col::<f32, 3>("(0.2 0.5 0.6"), None)
632632
}
633633

634634
#[test]
635635
fn str2col_base_paren_none2() {
636-
assert_eq!(str2col("0.2 0.5 0.6}"), None)
636+
assert_eq!(str2col::<f32, 3>("0.2 0.5 0.6}"), None)
637637
}
638638

639639
#[test]
640640
fn str2col_lch() {
641-
assert_eq!(str2col("lch(50, 30, 160)"), Some((Space::CIELCH, [50.0, 30.0, 160.0])))
641+
assert_eq!(
642+
str2col("lch(50, 30, 160)"),
643+
Some((Space::CIELCH, [50.0f32, 30.0, 160.0]))
644+
)
642645
}
643646

644647
#[test]
645648
fn str2col_lch_space() {
646-
assert_eq!(str2col("lch 50, 30, 160"), Some((Space::CIELCH, [50.0, 30.0, 160.0])))
649+
assert_eq!(
650+
str2col("lch 50, 30, 160"),
651+
Some((Space::CIELCH, [50.0f32, 30.0, 160.0]))
652+
)
647653
}
648654

649655
#[test]
650656
fn str2col_lch_colon() {
651-
assert_eq!(str2col("lch:50:30:160"), Some((Space::CIELCH, [50.0, 30.0, 160.0])))
657+
assert_eq!(str2col("lch:50:30:160"), Some((Space::CIELCH, [50.0f32, 30.0, 160.0])))
652658
}
653659

654660
#[test]
655661
fn str2col_lch_semicolon() {
656-
assert_eq!(str2col("lch;50;30;160"), Some((Space::CIELCH, [50.0, 30.0, 160.0])))
662+
assert_eq!(str2col("lch;50;30;160"), Some((Space::CIELCH, [50.0f32, 30.0, 160.0])))
657663
}
658664

659665
#[test]
660666
fn str2col_lch_mixed() {
661-
assert_eq!(str2col("lch; (50,30,160)"), Some((Space::CIELCH, [50.0, 30.0, 160.0])))
667+
assert_eq!(
668+
str2col("lch; (50,30,160)"),
669+
Some((Space::CIELCH, [50.0f32, 30.0, 160.0]))
670+
)
662671
}
663672

664673
#[test]
665674
fn str2col_lch_mixed2() {
666-
assert_eq!(str2col("lch(50; 30; 160)"), Some((Space::CIELCH, [50.0, 30.0, 160.0])))
675+
assert_eq!(
676+
str2col("lch(50; 30; 160)"),
677+
Some((Space::CIELCH, [50.0f32, 30.0, 160.0]))
678+
)
667679
}
668680

669681
#[test]
670682
fn str2col_lch_mixed3() {
671683
assert_eq!(
672684
str2col("lch (50 30 160)"),
673-
Some((Space::CIELCH, [50.0, 30.0, 160.0]))
685+
Some((Space::CIELCH, [50.0f32, 30.0, 160.0]))
674686
)
675687
}
676688

677689
#[test]
678690
fn str2col_hex() {
679-
assert_eq!(str2col(HEX), Some((Space::SRGB, irgb_to_srgb(IRGB))))
691+
assert_eq!(str2col(HEX), Some((Space::SRGB, irgb_to_srgb::<f32, 3>(IRGB))))
680692
}
681693

682694
#[test]
@@ -685,7 +697,11 @@ fn str2col_perc100() {
685697
str2col("oklch 100% 100% 100%"),
686698
Some((
687699
Space::OKLCH,
688-
[Space::OKLCH.srgb_quant100()[0], Space::OKLCH.srgb_quant100()[1], 360.0]
700+
[
701+
Space::OKLCH.srgb_quant100()[0],
702+
Space::OKLCH.srgb_quant100()[1],
703+
360.0f32
704+
]
689705
))
690706
)
691707
}
@@ -699,7 +715,7 @@ fn str2col_perc50() {
699715
[
700716
(Space::OKLCH.srgb_quant0()[0] + Space::OKLCH.srgb_quant100()[0]) / 2.0,
701717
(Space::OKLCH.srgb_quant0()[1] + Space::OKLCH.srgb_quant100()[1]) / 2.0,
702-
180.0,
718+
180.0f32,
703719
]
704720
))
705721
)
@@ -711,7 +727,7 @@ fn str2col_perc0() {
711727
str2col("oklch 0% 0% 0%"),
712728
Some((
713729
Space::OKLCH,
714-
[Space::OKLCH.srgb_quant0()[0], Space::OKLCH.srgb_quant0()[1], 0.0]
730+
[Space::OKLCH.srgb_quant0()[0], Space::OKLCH.srgb_quant0()[1], 0.0f32]
715731
))
716732
)
717733
}
@@ -722,40 +738,54 @@ fn str2col_perc_mix() {
722738
str2col("oklab 0.5 100.000% 0%"),
723739
Some((
724740
Space::OKLAB,
725-
[0.5, Space::OKLAB.srgb_quant100()[1], Space::OKLAB.srgb_quant0()[2]]
741+
[0.5f32, Space::OKLAB.srgb_quant100()[1], Space::OKLAB.srgb_quant0()[2]]
726742
))
727743
)
728744
}
729745

730746
#[test]
731747
fn str2col_perc_inval() {
732-
assert_eq!(str2col("oklab 0.5 100 % 0%"), None)
733-
}
734-
735-
#[test]
736-
fn str2col_perc_inval2() {
737-
assert_eq!(str2col("oklab 0.5% %100% 0%"), None)
748+
assert_eq!(str2col::<f32, 3>("oklab 0.5 100 % 0%"), None);
749+
assert_eq!(str2col::<f32, 3>("oklab 0.5% %100% 0%"), None);
750+
assert_eq!(str2col::<f32, 3>("oklab 0.5 100%% 0%"), None);
738751
}
739752

740753
#[test]
741-
fn str2col_perc_inval3() {
742-
assert_eq!(str2col("oklab 0.5 100%% 0%"), None)
754+
fn str2col_alpha() {
755+
assert_eq!(
756+
str2col("srgb 0, 0.5, 0.75, 1.0"),
757+
Some((Space::SRGB, [0f32, 0.5, 0.75, 1.0]))
758+
);
759+
assert_eq!(
760+
str2col("srgb 0, 0.5, 0.75, 1.0"),
761+
Some((Space::SRGB, [0f32, 0.5, 0.75]))
762+
);
763+
assert_eq!(
764+
str2col("srgb 10%, 20%, 50%, 80%"),
765+
Some((Space::SRGB, [0.1f32, 0.2, 0.5, 0.8]))
766+
);
767+
assert_eq!(
768+
str2col("srgb 10%, 20%, 50%, 80%"),
769+
Some((Space::SRGB, [0.1f32, 0.2, 0.5]))
770+
);
771+
let mut will_nan = str2col::<f32, 4>("srgb 0, 0.5, 0.75").unwrap();
772+
if will_nan.1[3].is_nan() {
773+
will_nan.1[3] = 0.12345
774+
}
775+
assert_eq!(will_nan, (Space::SRGB, [0f32, 0.5, 0.75, 0.12345]));
743776
}
744777

745778
#[test]
746779
fn str2space_base() {
747-
let pix: [f64; 3] = str2space("oklch : 0.62792590, 0.25768453, 29.22319405", Space::SRGB)
748-
.expect("STR2SPACE_BASE FAIL")
749-
.map(|v| v.into());
780+
let pix: [f64; 3] =
781+
str2space("oklch : 0.62792590, 0.25768453, 29.22319405", Space::SRGB).expect("STR2SPACE_BASE FAIL");
750782
let reference = [1.00000000, 0.00000000, 0.00000000];
751783
pix_cmp(&[pix], &[reference], 1e-3, &[]);
752784
}
753785

754786
#[test]
755787
fn str2space_hex() {
756-
let pix: [f64; 3] = str2space(" { #FF0000 } ", Space::OKLCH)
757-
.expect("STR2SPACE_HEX FAIL")
758-
.map(|v| v.into());
788+
let pix: [f64; 3] = str2space(" { #FF0000 } ", Space::OKLCH).expect("STR2SPACE_HEX FAIL");
759789
let reference = [0.62792590, 0.25768453, 29.22319405];
760790
pix_cmp(&[pix], &[reference], 1e-3, &[]);
761791
}

0 commit comments

Comments
 (0)