1use core::fmt;
4
5use zencodec::decode::{
6 ControlledIncrementalDecode, ControlledProgress, DecodeRowSink, Event, Fused,
7 IncrementalDecode, Input, InputRequest, MetadataUpdate, Progress, StepError,
8};
9use zencodec::operation::{
10 OperationPolicy, OperationReport, PolicyFailure, PolicySet, UnmetRequirements, resolve_boundary,
11};
12use zencodec::source::AccessPattern;
13use zencodec::{At, ImageInfo};
14use zenpixels::PixelDescriptor;
15
16#[derive(Debug)]
18#[non_exhaustive]
19pub enum PolicyDecodeError<E> {
20 Native(E),
22 Requirements(At<UnmetRequirements>),
24 Policy(At<PolicyFailure>),
26}
27impl<E: fmt::Display> fmt::Display for PolicyDecodeError<E> {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 match self {
30 Self::Native(e) => e.fmt(f),
31 Self::Requirements(e) => e.fmt(f),
32 Self::Policy(e) => e.fmt(f),
33 }
34 }
35}
36impl<E: core::error::Error + 'static> core::error::Error for PolicyDecodeError<E> {
37 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
38 Some(match self {
39 Self::Native(e) => e,
40 Self::Requirements(e) => e,
41 Self::Policy(e) => e,
42 })
43 }
44}
45
46pub struct PolicyDecoder<D, R> {
57 decoder: Option<Fused<D>>,
58 resolver: R,
59 preset: PolicySet,
60 report: OperationReport,
61 failed: bool,
62}
63impl<D, R> PolicyDecoder<D, R> {
64 pub fn new(decoder: D, resolver: R) -> Self {
67 Self {
68 decoder: Some(Fused::new(decoder)),
69 resolver,
70 preset: PolicySet::new(),
71 report: OperationReport::default(),
72 failed: false,
73 }
74 }
75 #[deprecated(note = "Pass PolicySet or BoundPolicy as the operation policy argument")]
79 pub fn with_policy_set(mut self, preset: PolicySet) -> Self {
80 self.preset = preset;
81 self
82 }
83 pub const fn report(&self) -> &OperationReport {
85 &self.report
86 }
87}
88impl<D, R: OperationPolicy> PolicyDecoder<D, R> {
89 pub fn try_new<E>(
118 factory: impl FnOnce() -> Result<D, E>,
119 policy: R,
120 pulse: Option<&dyn zencodec::Pulse>,
121 ) -> Result<Self, StepError<PolicyDecodeError<E>>> {
122 let pulse = pulse.unwrap_or(&zencodec::NoPulse);
123 pulse.check()?;
124 let decoder = Self::from_admitted_factory(factory, policy).map_err(StepError::Codec)?;
125 pulse.check()?;
126 Ok(decoder)
127 }
128
129 #[deprecated(
131 note = "Use try_new(factory, policy, pulse); pass None when no per-call control is needed"
132 )]
133 pub fn try_from_factory<E>(
134 factory: impl FnOnce() -> Result<D, E>,
135 policy: R,
136 ) -> Result<Self, PolicyDecodeError<E>> {
137 Self::from_admitted_factory(factory, policy)
138 }
139
140 fn from_admitted_factory<E>(
141 factory: impl FnOnce() -> Result<D, E>,
142 policy: R,
143 ) -> Result<Self, PolicyDecodeError<E>> {
144 if let Some(requirements) = policy.requirements() {
145 requirements.check_workspace(None).map_err(|error| {
146 PolicyDecodeError::Requirements(
147 At::wrap(error).at_named("controlled decoder factory admission"),
148 )
149 })?;
150 }
151 let decoder = factory().map_err(PolicyDecodeError::Native)?;
152 Ok(Self::new(decoder, policy))
153 }
154}
155impl<D: ControlledIncrementalDecode, R: OperationPolicy> IncrementalDecode for PolicyDecoder<D, R> {
156 type Error = PolicyDecodeError<D::Error>;
157 fn step(
158 &mut self,
159 input: Input<'_>,
160 sink: &mut dyn DecodeRowSink,
161 pulse: Option<&dyn zencodec::Pulse>,
162 ) -> Result<Progress, StepError<Self::Error>> {
163 if self.failed {
164 return Err(StepError::Finished);
165 }
166 self.failed = true;
168 let mut decoder = self.decoder.take().ok_or(StepError::Finished)?;
172 for requirements in [Some(self.preset), self.resolver.requirements()]
177 .into_iter()
178 .flatten()
179 {
180 requirements.check_workspace(None).map_err(|error| {
181 StepError::Codec(PolicyDecodeError::Requirements(
182 At::wrap(error).at_named("controlled decode workspace admission"),
183 ))
184 })?;
185 }
186 let progress = match decoder
187 .step_controlled(input, sink, pulse)
188 .map_err(|e| e.map_codec(PolicyDecodeError::Native))?
189 {
190 ControlledProgress::Decode(progress) => progress,
191 ControlledProgress::Suspended { consumed, boundary } => {
192 let (action, record) =
193 match resolve_boundary(boundary, &mut self.resolver, self.preset, pulse) {
194 Ok(answer) => answer,
195 Err(error) => {
196 self.report.record(error.error().record());
197 return Err(StepError::Codec(PolicyDecodeError::Policy(error)));
198 }
199 };
200 self.report.record(record);
201 decoder
202 .resume(boundary.id(), action, pulse)
203 .map_err(|e| e.map_codec(PolicyDecodeError::Native))?;
204 Progress::new(consumed, Event::Metadata(MetadataUpdate::Updated))
207 }
208 };
209 self.decoder = Some(decoder);
210 self.failed = false;
211 Ok(progress)
212 }
213 fn requested(&self) -> &[InputRequest] {
214 if self.failed {
215 &[]
216 } else {
217 self.decoder.as_ref().map_or(&[], |d| d.requested())
218 }
219 }
220 fn info(&self) -> Option<&ImageInfo> {
221 self.decoder.as_ref().and_then(|d| d.info())
222 }
223 fn take_details(&mut self) -> Option<zencodec::decode::DecodeDetails> {
224 if self.failed {
225 return None;
226 }
227 self.decoder.as_mut().and_then(|d| d.take_details())
228 }
229 fn output_descriptor(&self) -> Option<PixelDescriptor> {
230 self.decoder.as_ref().and_then(|d| d.output_descriptor())
231 }
232 fn access_pattern(&self) -> AccessPattern {
233 self.decoder
234 .as_ref()
235 .map_or(AccessPattern::default(), |d| d.access_pattern())
236 }
237}