1use core::{
2 fmt,
3 iter::FromIterator,
4 ops::{
5 Add, AddAssign, BitAnd, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Sub, SubAssign,
6 },
7};
8
9#[cfg(feature = "approx")]
10use approx::{AbsDiffEq, RelativeEq, UlpsEq};
11#[cfg(feature = "random")]
12use rand::{
13 distributions::{
14 uniform::{SampleBorrow, SampleUniform, Uniform, UniformSampler},
15 Distribution, Standard,
16 },
17 Rng,
18};
19
20use crate::{
21 blend::{PreAlpha, Premultiply},
22 bool_mask::HasBoolMask,
23 cast::ArrayCast,
24 clamp, clamp_assign,
25 convert::{FromColorUnclamped, IntoColorUnclamped},
26 num::{self, Arithmetics, One, PartialCmp, SaturatingAdd, SaturatingSub, Zero},
27 stimulus::Stimulus,
28 ArrayExt, Clamp, ClampAssign, GetHue, IsWithinBounds, Lighten, LightenAssign, Mix, MixAssign,
29 NextArray, Saturate, SaturateAssign, SetHue, ShiftHue, ShiftHueAssign, WithAlpha, WithHue,
30};
31
32#[derive(Clone, Copy, Debug)]
130#[repr(C)]
131pub struct Alpha<C, T> {
132 pub color: C,
134
135 pub alpha: T,
138}
139
140impl<C, A> Alpha<C, A> {
141 pub fn iter<'a>(&'a self) -> <&'a Self as IntoIterator>::IntoIter
143 where
144 &'a Self: IntoIterator,
145 {
146 self.into_iter()
147 }
148
149 pub fn iter_mut<'a>(&'a mut self) -> <&'a mut Self as IntoIterator>::IntoIter
151 where
152 &'a mut Self: IntoIterator,
153 {
154 self.into_iter()
155 }
156}
157
158impl<C: Premultiply> Alpha<C, C::Scalar> {
159 pub fn premultiply(self) -> PreAlpha<C> {
161 PreAlpha::new(self.color, self.alpha)
162 }
163}
164
165impl<C, T: Stimulus> Alpha<C, T> {
166 pub fn min_alpha() -> T {
168 T::zero()
169 }
170
171 pub fn max_alpha() -> T {
173 T::max_intensity()
174 }
175}
176
177impl<C, T> PartialEq for Alpha<C, T>
178where
179 T: PartialEq,
180 C: PartialEq,
181{
182 fn eq(&self, other: &Self) -> bool {
183 self.color == other.color && self.alpha == other.alpha
184 }
185}
186
187impl<C, T> Eq for Alpha<C, T>
188where
189 T: Eq,
190 C: Eq,
191{
192}
193
194impl<C1: WithAlpha<T>, C2, T> FromColorUnclamped<C1> for Alpha<C2, T>
195where
196 C1::Color: IntoColorUnclamped<C2>,
197{
198 fn from_color_unclamped(other: C1) -> Self {
199 let (color, alpha) = other.split();
200
201 Alpha {
202 color: color.into_color_unclamped(),
203 alpha,
204 }
205 }
206}
207
208impl<C, A> WithAlpha<A> for Alpha<C, A> {
209 type Color = C;
210 type WithAlpha = Self;
211
212 fn with_alpha(mut self, alpha: A) -> Self::WithAlpha {
213 self.alpha = alpha;
214 self
215 }
216
217 fn without_alpha(self) -> Self::Color {
218 self.color
219 }
220
221 fn split(self) -> (Self::Color, A) {
222 (self.color, self.alpha)
223 }
224}
225
226impl<C, T> Deref for Alpha<C, T> {
227 type Target = C;
228
229 fn deref(&self) -> &C {
230 &self.color
231 }
232}
233
234impl<C, T> DerefMut for Alpha<C, T> {
235 fn deref_mut(&mut self) -> &mut C {
236 &mut self.color
237 }
238}
239
240impl<C> Mix for Alpha<C, C::Scalar>
241where
242 C: Mix,
243 C::Scalar: Zero + One + num::Clamp + Arithmetics + Clone,
244{
245 type Scalar = C::Scalar;
246
247 #[inline]
248 fn mix(mut self, other: Self, factor: C::Scalar) -> Self {
249 let factor = clamp(factor, C::Scalar::zero(), C::Scalar::one());
250
251 self.color = self.color.mix(other.color, factor.clone());
252 self.alpha = self.alpha.clone() + factor * (other.alpha - self.alpha);
253
254 self
255 }
256}
257
258impl<C> MixAssign for Alpha<C, C::Scalar>
259where
260 C: MixAssign,
261 C::Scalar: Zero + One + num::Clamp + Arithmetics + AddAssign + Clone,
262{
263 type Scalar = C::Scalar;
264
265 #[inline]
266 fn mix_assign(&mut self, other: Self, factor: C::Scalar) {
267 let factor = clamp(factor, C::Scalar::zero(), C::Scalar::one());
268
269 self.color.mix_assign(other.color, factor.clone());
270 self.alpha += factor * (other.alpha - self.alpha.clone());
271 }
272}
273
274impl<C: Lighten> Lighten for Alpha<C, C::Scalar> {
275 type Scalar = C::Scalar;
276
277 #[inline]
278 fn lighten(self, factor: C::Scalar) -> Self {
279 Alpha {
280 color: self.color.lighten(factor),
281 alpha: self.alpha,
282 }
283 }
284
285 #[inline]
286 fn lighten_fixed(self, amount: C::Scalar) -> Self {
287 Alpha {
288 color: self.color.lighten_fixed(amount),
289 alpha: self.alpha,
290 }
291 }
292}
293
294impl<C: LightenAssign> LightenAssign for Alpha<C, C::Scalar> {
295 type Scalar = C::Scalar;
296
297 #[inline]
298 fn lighten_assign(&mut self, factor: C::Scalar) {
299 self.color.lighten_assign(factor);
300 }
301
302 #[inline]
303 fn lighten_fixed_assign(&mut self, amount: C::Scalar) {
304 self.color.lighten_fixed_assign(amount);
305 }
306}
307
308impl<C: GetHue, T> GetHue for Alpha<C, T> {
309 type Hue = C::Hue;
310
311 #[inline]
312 fn get_hue(&self) -> C::Hue {
313 self.color.get_hue()
314 }
315}
316
317impl<C, T, H> WithHue<H> for Alpha<C, T>
318where
319 C: WithHue<H>,
320{
321 #[inline]
322 fn with_hue(mut self, hue: H) -> Self {
323 self.color = self.color.with_hue(hue);
324 self
325 }
326}
327
328impl<C, T, H> SetHue<H> for Alpha<C, T>
329where
330 C: SetHue<H>,
331{
332 #[inline]
333 fn set_hue(&mut self, hue: H) {
334 self.color.set_hue(hue);
335 }
336}
337
338impl<C, T> ShiftHue for Alpha<C, T>
339where
340 C: ShiftHue,
341{
342 type Scalar = C::Scalar;
343
344 #[inline]
345 fn shift_hue(mut self, amount: Self::Scalar) -> Self {
346 self.color = self.color.shift_hue(amount);
347 self
348 }
349}
350
351impl<C, T> ShiftHueAssign for Alpha<C, T>
352where
353 C: ShiftHueAssign,
354{
355 type Scalar = C::Scalar;
356
357 #[inline]
358 fn shift_hue_assign(&mut self, amount: Self::Scalar) {
359 self.color.shift_hue_assign(amount);
360 }
361}
362
363impl<C: Saturate> Saturate for Alpha<C, C::Scalar> {
364 type Scalar = C::Scalar;
365
366 #[inline]
367 fn saturate(self, factor: C::Scalar) -> Self {
368 Alpha {
369 color: self.color.saturate(factor),
370 alpha: self.alpha,
371 }
372 }
373
374 #[inline]
375 fn saturate_fixed(self, amount: C::Scalar) -> Self {
376 Alpha {
377 color: self.color.saturate_fixed(amount),
378 alpha: self.alpha,
379 }
380 }
381}
382
383impl<C: SaturateAssign> SaturateAssign for Alpha<C, C::Scalar> {
384 type Scalar = C::Scalar;
385
386 #[inline]
387 fn saturate_assign(&mut self, factor: C::Scalar) {
388 self.color.saturate_assign(factor);
389 }
390
391 #[inline]
392 fn saturate_fixed_assign(&mut self, amount: C::Scalar) {
393 self.color.saturate_fixed_assign(amount);
394 }
395}
396
397impl<C, T> IsWithinBounds for Alpha<C, T>
398where
399 C: IsWithinBounds,
400 T: Stimulus + PartialCmp + IsWithinBounds<Mask = C::Mask>,
401 C::Mask: BitAnd<Output = C::Mask>,
402{
403 #[inline]
404 fn is_within_bounds(&self) -> C::Mask {
405 self.color.is_within_bounds()
406 & self.alpha.gt_eq(&Self::min_alpha())
407 & self.alpha.lt_eq(&Self::max_alpha())
408 }
409}
410
411impl<C, T> Clamp for Alpha<C, T>
412where
413 C: Clamp,
414 T: Stimulus + num::Clamp,
415{
416 #[inline]
417 fn clamp(self) -> Self {
418 Alpha {
419 color: self.color.clamp(),
420 alpha: clamp(self.alpha, Self::min_alpha(), Self::max_alpha()),
421 }
422 }
423}
424
425impl<C, T> ClampAssign for Alpha<C, T>
426where
427 C: ClampAssign,
428 T: Stimulus + num::ClampAssign,
429{
430 #[inline]
431 fn clamp_assign(&mut self) {
432 self.color.clamp_assign();
433 clamp_assign(&mut self.alpha, Self::min_alpha(), Self::max_alpha());
434 }
435}
436
437unsafe impl<C> ArrayCast for Alpha<C, <<C as ArrayCast>::Array as ArrayExt>::Item>
438where
439 C: ArrayCast,
440 C::Array: NextArray,
441{
442 type Array = <C::Array as NextArray>::Next;
443}
444
445impl<C, T> HasBoolMask for Alpha<C, T>
446where
447 C: HasBoolMask,
448 T: HasBoolMask<Mask = C::Mask>,
449{
450 type Mask = C::Mask;
451}
452
453impl<C: Default, T: Stimulus> Default for Alpha<C, T> {
454 fn default() -> Alpha<C, T> {
455 Alpha {
456 color: C::default(),
457 alpha: Self::max_alpha(),
458 }
459 }
460}
461
462#[cfg(feature = "approx")]
463impl<C, T> AbsDiffEq for Alpha<C, T>
464where
465 C: AbsDiffEq<Epsilon = T::Epsilon>,
466 T: AbsDiffEq,
467 T::Epsilon: Clone,
468{
469 type Epsilon = T::Epsilon;
470
471 fn default_epsilon() -> Self::Epsilon {
472 T::default_epsilon()
473 }
474
475 fn abs_diff_eq(&self, other: &Self, epsilon: T::Epsilon) -> bool {
476 self.color.abs_diff_eq(&other.color, epsilon.clone())
477 && self.alpha.abs_diff_eq(&other.alpha, epsilon)
478 }
479}
480
481#[cfg(feature = "approx")]
482impl<C, T> RelativeEq for Alpha<C, T>
483where
484 C: RelativeEq<Epsilon = T::Epsilon>,
485 T: RelativeEq,
486 T::Epsilon: Clone,
487{
488 fn default_max_relative() -> Self::Epsilon {
489 T::default_max_relative()
490 }
491
492 fn relative_eq(
493 &self,
494 other: &Alpha<C, T>,
495 epsilon: Self::Epsilon,
496 max_relative: Self::Epsilon,
497 ) -> bool {
498 self.color
499 .relative_eq(&other.color, epsilon.clone(), max_relative.clone())
500 && self.alpha.relative_eq(&other.alpha, epsilon, max_relative)
501 }
502}
503
504#[cfg(feature = "approx")]
505impl<C, T> UlpsEq for Alpha<C, T>
506where
507 C: UlpsEq<Epsilon = T::Epsilon>,
508 T: UlpsEq,
509 T::Epsilon: Clone,
510{
511 fn default_max_ulps() -> u32 {
512 T::default_max_ulps()
513 }
514
515 fn ulps_eq(&self, other: &Alpha<C, T>, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
516 self.color.ulps_eq(&other.color, epsilon.clone(), max_ulps)
517 && self.alpha.ulps_eq(&other.alpha, epsilon, max_ulps)
518 }
519}
520
521impl<C, T> Add for Alpha<C, T>
522where
523 C: Add,
524 T: Add,
525{
526 type Output = Alpha<C::Output, <T as Add>::Output>;
527
528 fn add(self, other: Alpha<C, T>) -> Self::Output {
529 Alpha {
530 color: self.color + other.color,
531 alpha: self.alpha + other.alpha,
532 }
533 }
534}
535
536impl<T, C> Add<T> for Alpha<C, T>
537where
538 T: Add + Clone,
539 C: Add<T>,
540{
541 type Output = Alpha<C::Output, <T as Add>::Output>;
542
543 fn add(self, c: T) -> Self::Output {
544 Alpha {
545 color: self.color + c.clone(),
546 alpha: self.alpha + c,
547 }
548 }
549}
550
551impl<C, T> AddAssign for Alpha<C, T>
552where
553 C: AddAssign,
554 T: AddAssign,
555{
556 fn add_assign(&mut self, other: Alpha<C, T>) {
557 self.color += other.color;
558 self.alpha += other.alpha;
559 }
560}
561
562impl<T, C> AddAssign<T> for Alpha<C, T>
563where
564 T: AddAssign + Clone,
565 C: AddAssign<T>,
566{
567 fn add_assign(&mut self, c: T) {
568 self.color += c.clone();
569 self.alpha += c;
570 }
571}
572
573impl<C, T> SaturatingAdd for Alpha<C, T>
574where
575 C: SaturatingAdd,
576 T: SaturatingAdd,
577{
578 type Output = Alpha<C::Output, <T as SaturatingAdd>::Output>;
579
580 fn saturating_add(self, other: Alpha<C, T>) -> Self::Output {
581 Alpha {
582 color: self.color.saturating_add(other.color),
583 alpha: self.alpha.saturating_add(other.alpha),
584 }
585 }
586}
587
588impl<T, C> SaturatingAdd<T> for Alpha<C, T>
589where
590 T: SaturatingAdd + Clone,
591 C: SaturatingAdd<T>,
592{
593 type Output = Alpha<C::Output, <T as SaturatingAdd>::Output>;
594
595 fn saturating_add(self, c: T) -> Self::Output {
596 Alpha {
597 color: self.color.saturating_add(c.clone()),
598 alpha: self.alpha.saturating_add(c),
599 }
600 }
601}
602
603impl<C, T> Sub for Alpha<C, T>
604where
605 C: Sub,
606 T: Sub,
607{
608 type Output = Alpha<C::Output, <T as Sub>::Output>;
609
610 fn sub(self, other: Alpha<C, T>) -> Self::Output {
611 Alpha {
612 color: self.color - other.color,
613 alpha: self.alpha - other.alpha,
614 }
615 }
616}
617
618impl<T, C> Sub<T> for Alpha<C, T>
619where
620 T: Sub + Clone,
621 C: Sub<T>,
622{
623 type Output = Alpha<C::Output, <T as Sub>::Output>;
624
625 fn sub(self, c: T) -> Self::Output {
626 Alpha {
627 color: self.color - c.clone(),
628 alpha: self.alpha - c,
629 }
630 }
631}
632
633impl<C, T> SubAssign for Alpha<C, T>
634where
635 C: SubAssign,
636 T: SubAssign,
637{
638 fn sub_assign(&mut self, other: Alpha<C, T>) {
639 self.color -= other.color;
640 self.alpha -= other.alpha;
641 }
642}
643
644impl<T, C> SubAssign<T> for Alpha<C, T>
645where
646 T: SubAssign + Clone,
647 C: SubAssign<T>,
648{
649 fn sub_assign(&mut self, c: T) {
650 self.color -= c.clone();
651 self.alpha -= c;
652 }
653}
654
655impl<C, T> SaturatingSub for Alpha<C, T>
656where
657 C: SaturatingSub,
658 T: SaturatingSub,
659{
660 type Output = Alpha<C::Output, <T as SaturatingSub>::Output>;
661
662 fn saturating_sub(self, other: Alpha<C, T>) -> Self::Output {
663 Alpha {
664 color: self.color.saturating_sub(other.color),
665 alpha: self.alpha.saturating_sub(other.alpha),
666 }
667 }
668}
669
670impl<T, C> SaturatingSub<T> for Alpha<C, T>
671where
672 T: SaturatingSub + Clone,
673 C: SaturatingSub<T>,
674{
675 type Output = Alpha<C::Output, <T as SaturatingSub>::Output>;
676
677 fn saturating_sub(self, c: T) -> Self::Output {
678 Alpha {
679 color: self.color.saturating_sub(c.clone()),
680 alpha: self.alpha.saturating_sub(c),
681 }
682 }
683}
684
685impl<C, T> Mul for Alpha<C, T>
686where
687 C: Mul,
688 T: Mul,
689{
690 type Output = Alpha<C::Output, <T as Mul>::Output>;
691
692 fn mul(self, other: Alpha<C, T>) -> Self::Output {
693 Alpha {
694 color: self.color * other.color,
695 alpha: self.alpha * other.alpha,
696 }
697 }
698}
699
700impl<T, C> Mul<T> for Alpha<C, T>
701where
702 T: Mul + Clone,
703 C: Mul<T>,
704{
705 type Output = Alpha<C::Output, <T as Mul>::Output>;
706
707 fn mul(self, c: T) -> Self::Output {
708 Alpha {
709 color: self.color * c.clone(),
710 alpha: self.alpha * c,
711 }
712 }
713}
714
715impl<C, T> MulAssign for Alpha<C, T>
716where
717 C: MulAssign,
718 T: MulAssign,
719{
720 fn mul_assign(&mut self, other: Alpha<C, T>) {
721 self.color *= other.color;
722 self.alpha *= other.alpha;
723 }
724}
725
726impl<T, C> MulAssign<T> for Alpha<C, T>
727where
728 T: MulAssign + Clone,
729 C: MulAssign<T>,
730{
731 fn mul_assign(&mut self, c: T) {
732 self.color *= c.clone();
733 self.alpha *= c;
734 }
735}
736
737impl<C, T> Div for Alpha<C, T>
738where
739 C: Div,
740 T: Div,
741{
742 type Output = Alpha<C::Output, <T as Div>::Output>;
743
744 fn div(self, other: Alpha<C, T>) -> Self::Output {
745 Alpha {
746 color: self.color / other.color,
747 alpha: self.alpha / other.alpha,
748 }
749 }
750}
751
752impl<T, C> Div<T> for Alpha<C, T>
753where
754 T: Div + Clone,
755 C: Div<T>,
756{
757 type Output = Alpha<C::Output, <T as Div>::Output>;
758
759 fn div(self, c: T) -> Self::Output {
760 Alpha {
761 color: self.color / c.clone(),
762 alpha: self.alpha / c,
763 }
764 }
765}
766
767impl<C, T> DivAssign for Alpha<C, T>
768where
769 C: DivAssign,
770 T: DivAssign,
771{
772 fn div_assign(&mut self, other: Alpha<C, T>) {
773 self.color /= other.color;
774 self.alpha /= other.alpha;
775 }
776}
777
778impl<T, C> DivAssign<T> for Alpha<C, T>
779where
780 T: DivAssign + Clone,
781 C: DivAssign<T>,
782{
783 fn div_assign(&mut self, c: T) {
784 self.color /= c.clone();
785 self.alpha /= c;
786 }
787}
788
789impl_array_casts!([C, T, const N: usize] Alpha<C, T>, [T; N], where Alpha<C, T>: ArrayCast<Array = [T; N]>);
790
791impl<C, T: Stimulus> From<C> for Alpha<C, T> {
792 fn from(color: C) -> Alpha<C, T> {
793 Alpha {
794 color,
795 alpha: Self::max_alpha(),
796 }
797 }
798}
799
800impl<C, T> fmt::LowerHex for Alpha<C, T>
801where
802 T: fmt::LowerHex,
803 C: fmt::LowerHex,
804{
805 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
806 let size = f.width().unwrap_or(::core::mem::size_of::<T>() * 2);
807 write!(
808 f,
809 "{:0width$x}{:0width$x}",
810 self.color,
811 self.alpha,
812 width = size
813 )
814 }
815}
816
817impl<C, T> fmt::UpperHex for Alpha<C, T>
818where
819 T: fmt::UpperHex,
820 C: fmt::UpperHex,
821{
822 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
823 let size = f.width().unwrap_or(::core::mem::size_of::<T>() * 2);
824 write!(
825 f,
826 "{:0width$X}{:0width$X}",
827 self.color,
828 self.alpha,
829 width = size
830 )
831 }
832}
833
834impl<Tc, Ta, C, A> Extend<Alpha<Tc, Ta>> for Alpha<C, A>
835where
836 C: Extend<Tc>,
837 A: Extend<Ta>,
838{
839 fn extend<T: IntoIterator<Item = Alpha<Tc, Ta>>>(&mut self, iter: T) {
840 for color in iter {
841 self.color.extend(core::iter::once(color.color));
842 self.alpha.extend(core::iter::once(color.alpha));
843 }
844 }
845}
846
847impl<Tc, Ta, C, A> FromIterator<Alpha<Tc, Ta>> for Alpha<C, A>
848where
849 C: Extend<Tc> + FromIterator<Tc>,
850 A: Extend<Ta> + Default,
851{
852 fn from_iter<T: IntoIterator<Item = Alpha<Tc, Ta>>>(iter: T) -> Self {
853 let mut result = Self {
854 color: C::from_iter(None), alpha: A::default(),
856 };
857
858 for color in iter {
859 result.color.extend(core::iter::once(color.color));
860 result.alpha.extend(core::iter::once(color.alpha));
861 }
862
863 result
864 }
865}
866
867pub struct Iter<C, A> {
869 pub(crate) color: C,
870 pub(crate) alpha: A,
871}
872
873impl<C, A> Iterator for Iter<C, A>
874where
875 C: Iterator,
876 A: Iterator,
877{
878 type Item = Alpha<C::Item, A::Item>;
879
880 fn next(&mut self) -> Option<Self::Item> {
881 let color = self.color.next();
882 let alpha = self.alpha.next();
883
884 if let (Some(color), Some(alpha)) = (color, alpha) {
885 Some(Alpha { color, alpha })
886 } else {
887 None
888 }
889 }
890
891 fn size_hint(&self) -> (usize, Option<usize>) {
892 let hint = self.color.size_hint();
893 debug_assert_eq!(
894 self.alpha.size_hint(),
895 hint,
896 "the color and alpha iterators have different size hints"
897 );
898
899 hint
900 }
901
902 fn count(self) -> usize {
903 let count = self.color.count();
904 debug_assert_eq!(
905 self.alpha.count(),
906 count,
907 "the color and alpha iterators have different counts"
908 );
909
910 count
911 }
912}
913
914impl<C, A> DoubleEndedIterator for Iter<C, A>
915where
916 C: DoubleEndedIterator,
917 A: DoubleEndedIterator,
918{
919 fn next_back(&mut self) -> Option<Self::Item> {
920 let color = self.color.next_back();
921 let alpha = self.alpha.next_back();
922
923 if let (Some(color), Some(alpha)) = (color, alpha) {
924 Some(Alpha { color, alpha })
925 } else {
926 None
927 }
928 }
929}
930
931impl<C, A> ExactSizeIterator for Iter<C, A>
932where
933 C: ExactSizeIterator,
934 A: ExactSizeIterator,
935{
936 fn len(&self) -> usize {
937 let len = self.color.len();
938 debug_assert_eq!(
939 self.alpha.len(),
940 len,
941 "the color and alpha iterators have different lengths"
942 );
943
944 len
945 }
946}
947
948#[cfg(feature = "serializing")]
949impl<C, T> serde::Serialize for Alpha<C, T>
950where
951 C: serde::Serialize,
952 T: serde::Serialize,
953{
954 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
955 where
956 S: serde::Serializer,
957 {
958 self.color.serialize(crate::serde::AlphaSerializer {
959 inner: serializer,
960 alpha: &self.alpha,
961 })
962 }
963}
964
965#[cfg(feature = "serializing")]
966impl<'de, C, T> serde::Deserialize<'de> for Alpha<C, T>
967where
968 C: serde::Deserialize<'de>,
969 T: serde::Deserialize<'de>,
970{
971 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
972 where
973 D: serde::Deserializer<'de>,
974 {
975 let mut alpha: Option<T> = None;
976
977 let color = C::deserialize(crate::serde::AlphaDeserializer {
978 inner: deserializer,
979 alpha: &mut alpha,
980 })?;
981
982 if let Some(alpha) = alpha {
983 Ok(Self { color, alpha })
984 } else {
985 Err(serde::de::Error::missing_field("alpha"))
986 }
987 }
988}
989
990#[cfg(feature = "random")]
991impl<C, T> Distribution<Alpha<C, T>> for Standard
992where
993 Standard: Distribution<C> + Distribution<T>,
994{
995 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Alpha<C, T> {
996 Alpha {
997 color: rng.gen(),
998 alpha: rng.gen(),
999 }
1000 }
1001}
1002
1003#[cfg(feature = "random")]
1005pub struct UniformAlpha<C, T>
1006where
1007 T: SampleUniform,
1008 C: SampleUniform,
1009{
1010 color: Uniform<C>,
1011 alpha: Uniform<T>,
1012}
1013
1014#[cfg(feature = "random")]
1015impl<C, T> SampleUniform for Alpha<C, T>
1016where
1017 T: Clone + SampleUniform,
1018 C: Clone + SampleUniform,
1019{
1020 type Sampler = UniformAlpha<C, T>;
1021}
1022
1023#[cfg(feature = "random")]
1024impl<C, T> UniformSampler for UniformAlpha<C, T>
1025where
1026 T: Clone + SampleUniform,
1027 C: Clone + SampleUniform,
1028{
1029 type X = Alpha<C, T>;
1030
1031 fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
1032 where
1033 B1: SampleBorrow<Self::X> + Sized,
1034 B2: SampleBorrow<Self::X> + Sized,
1035 {
1036 let low = low_b.borrow().clone();
1037 let high = high_b.borrow().clone();
1038
1039 UniformAlpha {
1040 color: Uniform::new::<C, _>(low.color, high.color),
1041 alpha: Uniform::new::<_, T>(low.alpha, high.alpha),
1042 }
1043 }
1044
1045 fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
1046 where
1047 B1: SampleBorrow<Self::X> + Sized,
1048 B2: SampleBorrow<Self::X> + Sized,
1049 {
1050 let low = low_b.borrow().clone();
1051 let high = high_b.borrow().clone();
1052
1053 UniformAlpha {
1054 color: Uniform::new_inclusive::<C, _>(low.color, high.color),
1055 alpha: Uniform::new_inclusive::<_, T>(low.alpha, high.alpha),
1056 }
1057 }
1058
1059 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Alpha<C, T> {
1060 Alpha {
1061 color: self.color.sample(rng),
1062 alpha: self.alpha.sample(rng),
1063 }
1064 }
1065}
1066
1067#[cfg(feature = "bytemuck")]
1068unsafe impl<C, T> bytemuck::Zeroable for Alpha<C, T>
1069where
1070 C: bytemuck::Zeroable,
1071 T: bytemuck::Zeroable,
1072{
1073}
1074
1075#[cfg(feature = "bytemuck")]
1081unsafe impl<C, T> bytemuck::Pod for Alpha<C, T>
1082where
1083 T: bytemuck::Pod,
1084 C: bytemuck::Pod + ArrayCast,
1085{
1086}
1087
1088#[cfg(test)]
1089mod test {
1090 use crate::encoding::Srgb;
1091 use crate::rgb::Rgba;
1092
1093 #[test]
1094 fn lower_hex() {
1095 assert_eq!(
1096 format!("{:x}", Rgba::<Srgb, u8>::new(171, 193, 35, 161)),
1097 "abc123a1"
1098 );
1099 }
1100
1101 #[test]
1102 fn lower_hex_small_numbers() {
1103 assert_eq!(
1104 format!("{:x}", Rgba::<Srgb, u8>::new(1, 2, 3, 4)),
1105 "01020304"
1106 );
1107 assert_eq!(
1108 format!("{:x}", Rgba::<Srgb, u16>::new(1, 2, 3, 4)),
1109 "0001000200030004"
1110 );
1111 assert_eq!(
1112 format!("{:x}", Rgba::<Srgb, u32>::new(1, 2, 3, 4)),
1113 "00000001000000020000000300000004"
1114 );
1115 assert_eq!(
1116 format!("{:x}", Rgba::<Srgb, u64>::new(1, 2, 3, 4)),
1117 "0000000000000001000000000000000200000000000000030000000000000004"
1118 );
1119 }
1120
1121 #[test]
1122 fn lower_hex_custom_width() {
1123 assert_eq!(
1124 format!("{:03x}", Rgba::<Srgb, u8>::new(1, 2, 3, 4)),
1125 "001002003004"
1126 );
1127 assert_eq!(
1128 format!("{:03x}", Rgba::<Srgb, u16>::new(1, 2, 3, 4)),
1129 "001002003004"
1130 );
1131 assert_eq!(
1132 format!("{:03x}", Rgba::<Srgb, u32>::new(1, 2, 3, 4)),
1133 "001002003004"
1134 );
1135 assert_eq!(
1136 format!("{:03x}", Rgba::<Srgb, u64>::new(1, 2, 3, 4)),
1137 "001002003004"
1138 );
1139 }
1140
1141 #[test]
1142 fn upper_hex() {
1143 assert_eq!(
1144 format!("{:X}", Rgba::<Srgb, u8>::new(171, 193, 35, 161)),
1145 "ABC123A1"
1146 );
1147 }
1148
1149 #[test]
1150 fn upper_hex_small_numbers() {
1151 assert_eq!(
1152 format!("{:X}", Rgba::<Srgb, u8>::new(1, 2, 3, 4)),
1153 "01020304"
1154 );
1155 assert_eq!(
1156 format!("{:X}", Rgba::<Srgb, u16>::new(1, 2, 3, 4)),
1157 "0001000200030004"
1158 );
1159 assert_eq!(
1160 format!("{:X}", Rgba::<Srgb, u32>::new(1, 2, 3, 4)),
1161 "00000001000000020000000300000004"
1162 );
1163 assert_eq!(
1164 format!("{:X}", Rgba::<Srgb, u64>::new(1, 2, 3, 4)),
1165 "0000000000000001000000000000000200000000000000030000000000000004"
1166 );
1167 }
1168
1169 #[test]
1170 fn upper_hex_custom_width() {
1171 assert_eq!(
1172 format!("{:03X}", Rgba::<Srgb, u8>::new(1, 2, 3, 4)),
1173 "001002003004"
1174 );
1175 assert_eq!(
1176 format!("{:03X}", Rgba::<Srgb, u16>::new(1, 2, 3, 4)),
1177 "001002003004"
1178 );
1179 assert_eq!(
1180 format!("{:03X}", Rgba::<Srgb, u32>::new(1, 2, 3, 4)),
1181 "001002003004"
1182 );
1183 assert_eq!(
1184 format!("{:03X}", Rgba::<Srgb, u64>::new(1, 2, 3, 4)),
1185 "001002003004"
1186 );
1187 }
1188
1189 #[test]
1190 fn check_min_max_components() {
1191 assert_eq!(Rgba::<Srgb>::min_alpha(), 0.0);
1192 assert_eq!(Rgba::<Srgb>::max_alpha(), 1.0);
1193 }
1194
1195 #[cfg(feature = "serializing")]
1196 #[test]
1197 fn serialize() {
1198 let color = Rgba::<Srgb>::new(0.3, 0.8, 0.1, 0.5);
1199
1200 assert_eq!(
1201 serde_json::to_string(&color).unwrap(),
1202 r#"{"red":0.3,"green":0.8,"blue":0.1,"alpha":0.5}"#
1203 );
1204
1205 assert_eq!(
1206 ron::to_string(&color).unwrap(),
1207 r#"(red:0.3,green:0.8,blue:0.1,alpha:0.5)"#
1208 );
1209 }
1210
1211 #[cfg(feature = "serializing")]
1212 #[test]
1213 fn deserialize() {
1214 let color = Rgba::<Srgb>::new(0.3, 0.8, 0.1, 0.5);
1215
1216 assert_eq!(
1217 serde_json::from_str::<Rgba<Srgb>>(r#"{"alpha":0.5,"red":0.3,"green":0.8,"blue":0.1}"#)
1218 .unwrap(),
1219 color
1220 );
1221
1222 assert_eq!(
1223 ron::from_str::<Rgba<Srgb>>(r#"(alpha:0.5,red:0.3,green:0.8,blue:0.1)"#).unwrap(),
1224 color
1225 );
1226
1227 assert_eq!(
1228 ron::from_str::<Rgba<Srgb>>(r#"Rgb(alpha:0.5,red:0.3,green:0.8,blue:0.1)"#).unwrap(),
1229 color
1230 );
1231 }
1232
1233 #[cfg(feature = "serializing")]
1234 #[test]
1235 fn serde_round_trips() {
1236 let color = Rgba::<Srgb>::new(0.3, 0.8, 0.1, 0.5);
1237
1238 assert_eq!(
1239 serde_json::from_str::<Rgba<Srgb>>(&serde_json::to_string(&color).unwrap()).unwrap(),
1240 color
1241 );
1242
1243 assert_eq!(
1244 ron::from_str::<Rgba<Srgb>>(&ron::to_string(&color).unwrap()).unwrap(),
1245 color
1246 );
1247 }
1248
1249 #[cfg(feature = "serializing")]
1250 #[test]
1251 fn serde_various_types() {
1252 macro_rules! test_roundtrip {
1253 ($value:expr $(, $ron_name:expr)?) => {
1254 let value = super::Alpha {
1255 color: $value,
1256 alpha: 0.5,
1257 };
1258 assert_eq!(
1259 serde_json::from_str::<super::Alpha<_, f32>>(
1260 &serde_json::to_string(&value).expect("json serialization")
1261 )
1262 .expect("json deserialization"),
1263 value
1264 );
1265
1266 let ron_string = ron::to_string(&value).expect("ron serialization");
1267 assert_eq!(
1268 ron::from_str::<super::Alpha<_, f32>>(&ron_string)
1269 .expect("ron deserialization"),
1270 value
1271 );
1272 $(
1273 assert_eq!(
1274 ron::from_str::<super::Alpha<_, f32>>(&format!("{}{ron_string}", $ron_name))
1275 .expect("ron deserialization"),
1276 value
1277 );
1278 )?
1279 };
1280 }
1281
1282 #[derive(Serialize, Deserialize, PartialEq, Debug)]
1283 struct Empty;
1284 #[derive(Serialize, Deserialize, PartialEq, Debug)]
1285 struct UnitTuple();
1286 #[derive(Serialize, Deserialize, PartialEq, Debug)]
1287 struct Newtype(f32);
1288 #[derive(Serialize, Deserialize, PartialEq, Debug)]
1289 struct Tuple(f32, f32);
1290 #[derive(Serialize, Deserialize, PartialEq, Debug)]
1291 struct Struct {
1292 value: f32,
1293 }
1294
1295 test_roundtrip!(());
1296 test_roundtrip!(Empty, "Empty");
1297 test_roundtrip!(UnitTuple(), "UnitTuple");
1298 test_roundtrip!(Newtype(0.1), "Newtype");
1299 test_roundtrip!(Tuple(0.1, 0.2), "Tuple");
1300 test_roundtrip!(Struct { value: 0.1 }, "Struct");
1301 }
1302
1303 test_uniform_distribution! {
1304 Rgba<Srgb, f32> {
1305 red: (0.0, 1.0),
1306 green: (0.0, 1.0),
1307 blue: (0.0, 1.0),
1308 alpha: (0.0, 1.0)
1309 },
1310 min: Rgba::new(0.0f32, 0.0, 0.0, 0.0),
1311 max: Rgba::new(1.0, 1.0, 1.0, 1.0)
1312 }
1313}