1use crate::ImageSize;
30use std::error::Error;
31use std::fmt::Display;
32
33#[derive(Copy, Clone, Debug)]
35pub struct PicScaleBufferMismatch {
36 pub expected: usize,
37 pub width: usize,
38 pub height: usize,
39 pub channels: usize,
40 pub slice_len: usize,
41}
42
43#[derive(Debug)]
45pub enum PicScaleError {
46 ZeroImageDimensions,
47 SourceImageIsTooLarge,
48 DestinationImageIsTooLarge,
49 BufferMismatch(PicScaleBufferMismatch),
50 InvalidStride(usize, usize),
51 UnsupportedBitDepth(usize),
52 UnknownResizingFilter,
53 OutOfMemory(usize),
54 InvalidScratchSize {
55 expected: usize,
56 size: usize,
57 },
58 InvalidSourceSize {
59 expected: ImageSize,
60 size: ImageSize,
61 },
62 InvalidDestinationSize {
63 expected: ImageSize,
64 size: ImageSize,
65 },
66}
67
68impl PicScaleError {
69 #[inline]
71 pub fn code(&self) -> usize {
72 match self {
73 PicScaleError::ZeroImageDimensions => 1,
74 PicScaleError::SourceImageIsTooLarge => 2,
75 PicScaleError::DestinationImageIsTooLarge => 3,
76 PicScaleError::BufferMismatch(_) => 4,
77 PicScaleError::InvalidStride(_, _) => 5,
78 PicScaleError::UnsupportedBitDepth(_) => 6,
79 PicScaleError::UnknownResizingFilter => 7,
80 PicScaleError::OutOfMemory(_) => 8,
81 PicScaleError::InvalidScratchSize { .. } => 9,
82 PicScaleError::InvalidSourceSize { .. } => 10,
83 PicScaleError::InvalidDestinationSize { .. } => 11,
84 }
85 }
86}
87
88impl Display for PicScaleError {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 match self {
91 PicScaleError::InvalidStride(min_stride, real_stride) => f.write_fmt(format_args!(
92 "Stride must be at least {min_stride}, but received {real_stride}",
93 )),
94 PicScaleError::ZeroImageDimensions => {
95 f.write_str("One of image dimensions is 0, this should not happen")
96 }
97 PicScaleError::SourceImageIsTooLarge => {
98 f.write_str("Input image larger than memory capabilities")
99 }
100 PicScaleError::DestinationImageIsTooLarge => {
101 f.write_str("Destination image larger than memory capabilities")
102 }
103 PicScaleError::BufferMismatch(buffer_mismatch) => f.write_fmt(format_args!(
104 "Image buffer len expected to be {} [w({})*h({})*channels({})] but received {}",
105 buffer_mismatch.expected,
106 buffer_mismatch.width,
107 buffer_mismatch.height,
108 buffer_mismatch.channels,
109 buffer_mismatch.slice_len,
110 )),
111 PicScaleError::UnsupportedBitDepth(depth) => {
112 f.write_fmt(format_args!("Bit-depth must be in [1, 16] but got {depth}",))
113 }
114 PicScaleError::UnknownResizingFilter => {
115 f.write_str("Unknown resizing filter was requested")
116 }
117 PicScaleError::OutOfMemory(capacity) => f.write_fmt(format_args!(
118 "There is no enough memory to allocate {capacity} bytes"
119 )),
120 PicScaleError::InvalidScratchSize { expected, size } => f.write_fmt(format_args!(
121 "Scratch size must be at least {expected} bytes, but received {size}",
122 )),
123 PicScaleError::InvalidSourceSize { expected, size } => f.write_fmt(format_args!(
124 "Source size must be at least {:?} bytes, but received {:?}",
125 expected, size
126 )),
127 PicScaleError::InvalidDestinationSize { expected, size } => f.write_fmt(format_args!(
128 "Destination size must be at least {:?} bytes, but received {:?}",
129 expected, size
130 )),
131 }
132 }
133}
134
135impl Error for PicScaleError {}
136
137macro_rules! try_vec {
138 () => {
139 Vec::new()
140 };
141 ($elem:expr; $n:expr) => {{
142 let mut v = Vec::new();
143 v.try_reserve_exact($n)
144 .map_err(|_| crate::validation::PicScaleError::OutOfMemory($n))?;
145 v.resize($n, $elem);
146 v
147 }};
148}
149
150pub(crate) use try_vec;
151
152macro_rules! validate_scratch {
153 ($scratch: expr, $required_size: expr) => {{
154 if $scratch.len() < $required_size {
155 return Err(PicScaleError::InvalidScratchSize {
156 expected: $required_size,
157 size: $scratch.len(),
158 });
159 }
160 &mut $scratch[..$required_size]
161 }};
162}
163
164pub(crate) use validate_scratch;
165
166macro_rules! validate_sizes {
167 ($store: expr, $into: expr, $src_size: expr, $dst_size: expr) => {{
168 $into.validate()?;
169 $store.validate()?;
170 if $store.width != $src_size.width && $store.height != $src_size.height {
171 return Err(PicScaleError::InvalidSourceSize {
172 expected: $src_size,
173 size: $store.size(),
174 });
175 }
176 if $into.width != $dst_size.width && $into.height != $dst_size.height {
177 return Err(PicScaleError::InvalidDestinationSize {
178 expected: $src_size,
179 size: $store.size(),
180 });
181 }
182 if $store.width == $into.width && $store.height == $into.height {
183 $store.copied_to_mut($into);
184 return Ok(());
185 }
186 }};
187}
188
189pub(crate) use validate_sizes;