picto/buffer/
cast.rs

1//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2//                    Version 2, December 2004
3//
4// Copyleft (ↄ) meh. <meh@schizofreni.co> | http://meh.schizofreni.co
5//
6// Everyone is permitted to copy and distribute verbatim or modified
7// copies of this license document, and changing it is allowed as long
8// as the name is changed.
9//
10//            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11//   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12//
13//  0. You just DO WHAT THE FUCK YOU WANT TO.
14
15use std::borrow::Cow;
16
17use crate::{
18	buffer::Buffer,
19	pixel::{self, Pixel},
20};
21
22/// This trait is used for optimizations where turning a `Buffer` into another
23/// can just reuse the inner data as is.
24pub trait Into<P, C>
25where
26	P: Pixel<C>,
27	C: pixel::Channel,
28{
29	/// Convert `Self` into a `Buffer`.
30	fn into(self) -> Buffer<P, C, Vec<C>>;
31}
32
33/// This trait is used for optimizations where the type can be converted to an
34/// `&[u8]` as is without going through any conversions.
35pub trait Bytes<P, C>
36where
37	P: Pixel<C>,
38	C: pixel::Channel,
39{
40	/// Convert `Self` to a byte slice.
41	fn bytes(&self) -> Cow<[u8]>;
42}
43
44#[cfg(not(feature = "nightly"))]
45mod stable {
46	use std::{borrow::Cow, ops::Deref};
47
48	use crate::{buffer::Buffer, pixel};
49
50	impl<PI, CI, DI, PO, CO> super::Into<PO, CO> for Buffer<PI, CI, DI>
51	where
52		PI: pixel::Read<CI>,
53		CI: pixel::Channel,
54		DI: Deref<Target = [CI]>,
55		PO: pixel::Write<CO>,
56		PO: From<PI>,
57		CO: pixel::Channel,
58	{
59		#[inline]
60		fn into(self) -> Buffer<PO, CO, Vec<CO>> {
61			self.convert::<PO, CO>()
62		}
63	}
64
65	impl<PI, CI, DI, PO, CO> super::Bytes<PO, CO> for Buffer<PI, CI, DI>
66	where
67		PI: pixel::Read<CI>,
68		PI: Into<PO>,
69		CI: pixel::Channel,
70		DI: Deref<Target = [CI]>,
71		PO: pixel::Write<CO> + pixel::Write<u8>,
72		CO: pixel::Channel,
73	{
74		#[inline]
75		fn bytes(&self) -> Cow<[u8]> {
76			Cow::Owned(self.convert::<PO, u8>().into_raw())
77		}
78	}
79}
80
81#[cfg(feature = "nightly")]
82mod nightly {
83	use std::{borrow::Cow, mem, ops::Deref, slice};
84
85	use buffer::Buffer;
86	use color::{Hsl, Hsla, Hsv, Hsva, Hwb, Hwba, Lab, Laba, Lch, Lcha, Luma, Lumaa, Rgb, Rgba, Xyz, Xyza, Yxy, Yxya};
87	use num::Float;
88	use pixel;
89
90	impl<PI, CI, DI, CO, PO> super::Into<PO, CO> for Buffer<PI, CI, DI>
91	where
92		PI: pixel::Read<CI>,
93		CI: pixel::Channel,
94		DI: Deref<Target = [CI]>,
95		PO: pixel::Write<CO>,
96		PO: From<PI>,
97		CO: pixel::Channel,
98	{
99		#[inline]
100		default fn into(self) -> Buffer<PO, CO, Vec<CO>> {
101			self.convert::<PO, CO>()
102		}
103	}
104
105	impl<PI, CI, DI, PO, CO> super::Bytes<PO, CO> for Buffer<PI, CI, DI>
106	where
107		PI: pixel::Read<CI>,
108		PI: Into<PO>,
109		CI: pixel::Channel,
110		DI: Deref<Target = [CI]>,
111		PO: pixel::Write<CO> + pixel::Write<u8>,
112		CO: pixel::Channel,
113	{
114		#[inline]
115		default fn bytes(&self) -> Cow<[u8]> {
116			Cow::Owned(self.convert::<PO, u8>().into_raw())
117		}
118	}
119
120	macro_rules! impl_for {
121		()     => ();
122		(impl) => ();
123
124		(impl ($ch:ident, $px:ident)) => (
125			impl<T: Float + Copy + 'static> super::Into<$px<T>, $ch> for Buffer<$px<T>, $ch, Vec<$ch>> {
126				#[inline]
127				fn into(self) -> Self {
128					self
129				}
130			}
131
132			impl<T: Float + Copy + 'static> super::Bytes<$px<T>, $ch> for Buffer<$px<T>, $ch, Vec<$ch>> {
133				#[inline]
134				fn bytes(&self) -> Cow<[u8]> {
135					let slice: &[$ch] = &*self;
136
137					Cow::Borrowed(unsafe {
138						slice::from_raw_parts(slice.as_ptr() as *const _, slice.len() * mem::size_of::<$ch>())
139					})
140				}
141			}
142		);
143
144		(impl ($ch:ident, $px:ident), $($rest:tt)*) => (
145			impl_for!(impl ($ch, $px));
146			impl_for!(impl $($rest)*);
147		);
148
149		($($rest:tt)*) => (
150			impl_for!(impl $($rest)*);
151		);
152	}
153
154	impl_for! {
155		(u8, Luma),  (u8, Rgb),  (u8, Hsl),  (u8, Hsv),  (u8, Hwb),  (u8, Lab),  (u8, Lch),  (u8, Xyz),  (u8, Yxy),
156		(u8, Lumaa), (u8, Rgba), (u8, Hsla), (u8, Hsva), (u8, Hwba), (u8, Laba), (u8, Lcha), (u8, Xyza), (u8, Yxya),
157	}
158
159	impl_for! {
160		(u16, Luma),  (u16, Rgb),  (u16, Hsl),  (u16, Hsv),  (u16, Hwb),  (u16, Lab),  (u16, Lch),  (u16, Xyz),  (u16, Yxy),
161		(u16, Lumaa), (u16, Rgba), (u16, Hsla), (u16, Hsva), (u16, Hwba), (u16, Laba), (u16, Lcha), (u16, Xyza), (u16, Yxya),
162	}
163
164	impl_for! {
165		(f32, Luma),  (f32, Rgb),  (f32, Hsl),  (f32, Hsv),  (f32, Hwb),  (f32, Lab),  (f32, Lch),  (f32, Xyz),  (f32, Yxy),
166		(f32, Lumaa), (f32, Rgba), (f32, Hsla), (f32, Hsva), (f32, Hwba), (f32, Laba), (f32, Lcha), (f32, Xyza), (f32, Yxya),
167	}
168
169	impl_for! {
170		(f64, Luma),  (f64, Rgb),  (f64, Hsl),  (f64, Hsv),  (f64, Hwb),  (f64, Lab),  (f64, Lch),  (f64, Xyz),  (f64, Yxy),
171		(f64, Lumaa), (f64, Rgba), (f64, Hsla), (f64, Hsva), (f64, Hwba), (f64, Laba), (f64, Lcha), (f64, Xyza), (f64, Yxya),
172	}
173}