Skip to main content

signinum_core/
traits.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use alloc::vec::Vec;
4
5use crate::{
6    accelerator::{DeviceMemoryRange, ExecutionStats, SurfaceResidency},
7    backend::{BackendKind, BackendRequest},
8    context::{CodecContext, DecoderContext},
9    error::CodecError,
10    pixel::PixelFormat,
11    row_sink::RowSink,
12    sample::Sample,
13    scale::Downscale,
14    scratch::ScratchPool,
15    types::{DecodeOutcome, DecodeRequest, Info, Rect},
16};
17
18/// Error wrapper used by row-streaming decode when either the codec or the
19/// caller-provided row sink can fail.
20#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
21pub enum DecodeRowsError<D, E>
22where
23    D: core::error::Error + 'static,
24    E: core::error::Error + 'static,
25{
26    #[error(transparent)]
27    /// Codec decode failure.
28    Decode(D),
29    #[error(transparent)]
30    /// Caller-provided row sink failure.
31    Sink(E),
32}
33
34/// Common associated types shared by image codecs.
35pub trait ImageCodec {
36    /// Codec-specific error type.
37    type Error: CodecError;
38    /// Non-fatal warning type returned in successful decode outcomes.
39    type Warning: core::fmt::Debug + core::fmt::Display + Send + Sync + 'static;
40    /// Caller-owned scratch pool type used to reuse allocations.
41    type Pool: ScratchPool;
42}
43
44/// Decoded image data resident on a specific backend.
45pub trait DeviceSurface {
46    /// Backend that owns or produced the surface.
47    fn backend_kind(&self) -> BackendKind;
48    /// Memory residency of the surface.
49    fn residency(&self) -> SurfaceResidency {
50        SurfaceResidency::for_backend(self.backend_kind())
51    }
52    /// Surface dimensions in pixels.
53    fn dimensions(&self) -> (u32, u32);
54    /// Pixel format stored by the surface.
55    fn pixel_format(&self) -> PixelFormat;
56    /// Number of bytes represented by the surface.
57    fn byte_len(&self) -> usize;
58    /// Execution statistics attached to the surface.
59    fn execution_stats(&self) -> ExecutionStats {
60        ExecutionStats::default()
61    }
62    /// Backend-visible memory range, when the backend can expose one safely.
63    fn memory_range(&self) -> Option<DeviceMemoryRange> {
64        None
65    }
66}
67
68/// Submitted device decode operation that can be waited on for completion.
69pub trait DeviceSubmission {
70    /// Completed output type.
71    type Output;
72    /// Submission or decode error type.
73    type Error;
74
75    /// Wait for the submission and return its output.
76    fn wait(self) -> Result<Self::Output, Self::Error>;
77}
78
79/// Already-completed submission used by synchronous fallback paths.
80#[derive(Debug)]
81pub struct ReadySubmission<T, E>(Result<T, E>);
82
83impl<T, E> ReadySubmission<T, E> {
84    /// Wrap an immediate result as a submission.
85    pub fn from_result(result: Result<T, E>) -> Self {
86        Self(result)
87    }
88}
89
90impl<T, E> DeviceSubmission for ReadySubmission<T, E> {
91    type Output = T;
92    type Error = E;
93
94    fn wait(self) -> Result<Self::Output, Self::Error> {
95        self.0
96    }
97}
98
99/// Mutable device session that tracks submitted backend work.
100pub trait DeviceSubmitSession {
101    /// Record a submitted device operation.
102    fn record_submit(&mut self);
103}
104
105/// Record a device submission and wrap an immediate result as ready.
106pub fn submit_ready_device<S, T, E>(
107    session: &mut S,
108    submit: impl FnOnce(&mut S) -> Result<T, E>,
109) -> ReadySubmission<T, E>
110where
111    S: DeviceSubmitSession + ?Sized,
112{
113    session.record_submit();
114    ReadySubmission::from_result(submit(session))
115}
116
117/// Borrowed-image decode API for codecs that parse compressed bytes directly.
118pub trait ImageDecode<'a>: ImageCodec + Sized + 'a {
119    /// Borrowed parse product that can later construct a decoder.
120    type View: 'a;
121
122    /// Inspect metadata without decoding pixels.
123    fn inspect(input: &'a [u8]) -> Result<Info, Self::Error>;
124    /// Parse compressed bytes into a borrowed view.
125    fn parse(input: &'a [u8]) -> Result<Self::View, Self::Error>;
126    /// Build a decoder from a parsed view.
127    fn from_view(view: Self::View) -> Result<Self, Self::Error>;
128
129    /// Decode the full image into caller-owned output.
130    fn decode_into(
131        &mut self,
132        out: &mut [u8],
133        stride: usize,
134        fmt: PixelFormat,
135    ) -> Result<DecodeOutcome<Self::Warning>, Self::Error>;
136
137    /// Decode the full image into caller-owned output with reusable scratch.
138    fn decode_into_with_scratch(
139        &mut self,
140        pool: &mut Self::Pool,
141        out: &mut [u8],
142        stride: usize,
143        fmt: PixelFormat,
144    ) -> Result<DecodeOutcome<Self::Warning>, Self::Error>;
145
146    /// Decode a source-coordinate region into caller-owned output.
147    fn decode_region_into(
148        &mut self,
149        pool: &mut Self::Pool,
150        out: &mut [u8],
151        stride: usize,
152        fmt: PixelFormat,
153        roi: Rect,
154    ) -> Result<DecodeOutcome<Self::Warning>, Self::Error>;
155
156    /// Decode the full image at reduced resolution into caller-owned output.
157    fn decode_scaled_into(
158        &mut self,
159        pool: &mut Self::Pool,
160        out: &mut [u8],
161        stride: usize,
162        fmt: PixelFormat,
163        scale: Downscale,
164    ) -> Result<DecodeOutcome<Self::Warning>, Self::Error>;
165
166    /// Decode a source-coordinate region at reduced resolution into caller-owned output.
167    fn decode_region_scaled_into(
168        &mut self,
169        pool: &mut Self::Pool,
170        out: &mut [u8],
171        stride: usize,
172        fmt: PixelFormat,
173        roi: Rect,
174        scale: Downscale,
175    ) -> Result<DecodeOutcome<Self::Warning>, Self::Error>;
176
177    /// Decode a normalized full/ROI/scaled request into caller-owned output.
178    fn decode_request_into(
179        &mut self,
180        pool: &mut Self::Pool,
181        out: &mut [u8],
182        stride: usize,
183        fmt: PixelFormat,
184        request: DecodeRequest,
185    ) -> Result<DecodeOutcome<Self::Warning>, Self::Error> {
186        match (request.roi, request.scale) {
187            (None, Downscale::None) => self.decode_into_with_scratch(pool, out, stride, fmt),
188            (Some(roi), Downscale::None) => self.decode_region_into(pool, out, stride, fmt, roi),
189            (None, scale) => self.decode_scaled_into(pool, out, stride, fmt, scale),
190            (Some(roi), scale) => {
191                self.decode_region_scaled_into(pool, out, stride, fmt, roi, scale)
192            }
193        }
194    }
195}
196
197/// Decode API for implementations that can submit work to a device backend.
198pub trait ImageDecodeSubmit<'a>: ImageDecode<'a> {
199    /// Mutable session state shared across submissions.
200    type Session: Default + Send;
201    /// Device surface returned by completed submissions.
202    type DeviceSurface: DeviceSurface;
203    /// Submission handle type.
204    type SubmittedSurface: DeviceSubmission<Output = Self::DeviceSurface, Error = Self::Error>;
205
206    /// Submit full-image decode to the requested backend.
207    fn submit_to_device(
208        &mut self,
209        session: &mut Self::Session,
210        fmt: PixelFormat,
211        backend: BackendRequest,
212    ) -> Result<Self::SubmittedSurface, Self::Error>;
213
214    /// Submit region decode to the requested backend.
215    fn submit_region_to_device(
216        &mut self,
217        session: &mut Self::Session,
218        fmt: PixelFormat,
219        roi: Rect,
220        backend: BackendRequest,
221    ) -> Result<Self::SubmittedSurface, Self::Error>;
222
223    /// Submit reduced-resolution decode to the requested backend.
224    fn submit_scaled_to_device(
225        &mut self,
226        session: &mut Self::Session,
227        fmt: PixelFormat,
228        scale: Downscale,
229        backend: BackendRequest,
230    ) -> Result<Self::SubmittedSurface, Self::Error>;
231
232    /// Submit region decode at reduced resolution to the requested backend.
233    fn submit_region_scaled_to_device(
234        &mut self,
235        session: &mut Self::Session,
236        fmt: PixelFormat,
237        roi: Rect,
238        scale: Downscale,
239        backend: BackendRequest,
240    ) -> Result<Self::SubmittedSurface, Self::Error>;
241
242    /// Submit a normalized full/ROI/scaled decode request to a device backend.
243    fn submit_request_to_device(
244        &mut self,
245        session: &mut Self::Session,
246        fmt: PixelFormat,
247        backend: BackendRequest,
248        request: DecodeRequest,
249    ) -> Result<Self::SubmittedSurface, Self::Error> {
250        match (request.roi, request.scale) {
251            (None, Downscale::None) => self.submit_to_device(session, fmt, backend),
252            (Some(roi), Downscale::None) => {
253                self.submit_region_to_device(session, fmt, roi, backend)
254            }
255            (None, scale) => self.submit_scaled_to_device(session, fmt, scale, backend),
256            (Some(roi), scale) => {
257                self.submit_region_scaled_to_device(session, fmt, roi, scale, backend)
258            }
259        }
260    }
261}
262
263/// Synchronous device-output decode API.
264pub trait ImageDecodeDevice<'a>: ImageDecode<'a> {
265    /// Device surface returned by decode calls.
266    type DeviceSurface: DeviceSurface;
267
268    /// Decode the full image to the requested backend.
269    fn decode_to_device(
270        &mut self,
271        fmt: PixelFormat,
272        backend: BackendRequest,
273    ) -> Result<<Self as ImageDecodeDevice<'a>>::DeviceSurface, Self::Error>
274    where
275        Self: ImageDecodeSubmit<'a, DeviceSurface = <Self as ImageDecodeDevice<'a>>::DeviceSurface>,
276    {
277        let mut session = <Self as ImageDecodeSubmit<'a>>::Session::default();
278        <Self as ImageDecodeSubmit<'a>>::submit_to_device(self, &mut session, fmt, backend)?.wait()
279    }
280
281    /// Decode a source-coordinate region to the requested backend.
282    fn decode_region_to_device(
283        &mut self,
284        fmt: PixelFormat,
285        roi: Rect,
286        backend: BackendRequest,
287    ) -> Result<<Self as ImageDecodeDevice<'a>>::DeviceSurface, Self::Error>
288    where
289        Self: ImageDecodeSubmit<'a, DeviceSurface = <Self as ImageDecodeDevice<'a>>::DeviceSurface>,
290    {
291        let mut session = <Self as ImageDecodeSubmit<'a>>::Session::default();
292        <Self as ImageDecodeSubmit<'a>>::submit_region_to_device(
293            self,
294            &mut session,
295            fmt,
296            roi,
297            backend,
298        )?
299        .wait()
300    }
301
302    /// Decode the full image at reduced resolution to the requested backend.
303    fn decode_scaled_to_device(
304        &mut self,
305        fmt: PixelFormat,
306        scale: Downscale,
307        backend: BackendRequest,
308    ) -> Result<<Self as ImageDecodeDevice<'a>>::DeviceSurface, Self::Error>
309    where
310        Self: ImageDecodeSubmit<'a, DeviceSurface = <Self as ImageDecodeDevice<'a>>::DeviceSurface>,
311    {
312        let mut session = <Self as ImageDecodeSubmit<'a>>::Session::default();
313        <Self as ImageDecodeSubmit<'a>>::submit_scaled_to_device(
314            self,
315            &mut session,
316            fmt,
317            scale,
318            backend,
319        )?
320        .wait()
321    }
322
323    /// Decode a source-coordinate region at reduced resolution to the requested backend.
324    fn decode_region_scaled_to_device(
325        &mut self,
326        fmt: PixelFormat,
327        roi: Rect,
328        scale: Downscale,
329        backend: BackendRequest,
330    ) -> Result<<Self as ImageDecodeDevice<'a>>::DeviceSurface, Self::Error>
331    where
332        Self: ImageDecodeSubmit<'a, DeviceSurface = <Self as ImageDecodeDevice<'a>>::DeviceSurface>,
333    {
334        let mut session = <Self as ImageDecodeSubmit<'a>>::Session::default();
335        <Self as ImageDecodeSubmit<'a>>::submit_region_scaled_to_device(
336            self,
337            &mut session,
338            fmt,
339            roi,
340            scale,
341            backend,
342        )?
343        .wait()
344    }
345}
346
347/// Row-streaming decode API for large images or stripe-oriented callers.
348pub trait ImageDecodeRows<'a, S: Sample>: ImageDecode<'a> {
349    /// Decode rows into `sink` without requiring one contiguous output buffer.
350    fn decode_rows<R: RowSink<S>>(
351        &mut self,
352        sink: &mut R,
353    ) -> Result<DecodeOutcome<Self::Warning>, DecodeRowsError<Self::Error, R::Error>>;
354}
355
356/// Stateless tile-batch decode helpers that reuse caller-owned context.
357pub trait TileBatchDecode: ImageCodec {
358    /// Codec-specific context cached across tiles.
359    type Context: CodecContext;
360
361    /// Decode one tile into caller-owned output.
362    fn decode_tile<'a>(
363        ctx: &mut DecoderContext<Self::Context>,
364        pool: &mut Self::Pool,
365        input: &'a [u8],
366        out: &mut [u8],
367        stride: usize,
368        fmt: PixelFormat,
369    ) -> Result<DecodeOutcome<Self::Warning>, Self::Error>;
370
371    /// Decode one tile region into caller-owned output.
372    fn decode_tile_region<'a>(
373        ctx: &mut DecoderContext<Self::Context>,
374        pool: &mut Self::Pool,
375        input: &'a [u8],
376        out: &mut [u8],
377        stride: usize,
378        fmt: PixelFormat,
379        roi: Rect,
380    ) -> Result<DecodeOutcome<Self::Warning>, Self::Error>;
381
382    /// Decode one tile at reduced resolution into caller-owned output.
383    fn decode_tile_scaled<'a>(
384        ctx: &mut DecoderContext<Self::Context>,
385        pool: &mut Self::Pool,
386        input: &'a [u8],
387        out: &mut [u8],
388        stride: usize,
389        fmt: PixelFormat,
390        scale: Downscale,
391    ) -> Result<DecodeOutcome<Self::Warning>, Self::Error>;
392
393    /// Decode one tile region at reduced resolution into caller-owned output.
394    #[allow(clippy::too_many_arguments)]
395    fn decode_tile_region_scaled<'a>(
396        ctx: &mut DecoderContext<Self::Context>,
397        pool: &mut Self::Pool,
398        input: &'a [u8],
399        out: &mut [u8],
400        stride: usize,
401        fmt: PixelFormat,
402        roi: Rect,
403        scale: Downscale,
404    ) -> Result<DecodeOutcome<Self::Warning>, Self::Error>;
405
406    /// Decode one tile for a normalized full/ROI/scaled request.
407    fn decode_tile_request<'a>(
408        ctx: &mut DecoderContext<Self::Context>,
409        pool: &mut Self::Pool,
410        input: &'a [u8],
411        out: &mut [u8],
412        stride: usize,
413        fmt: PixelFormat,
414        request: DecodeRequest,
415    ) -> Result<DecodeOutcome<Self::Warning>, Self::Error> {
416        match (request.roi, request.scale) {
417            (None, Downscale::None) => Self::decode_tile(ctx, pool, input, out, stride, fmt),
418            (Some(roi), Downscale::None) => {
419                Self::decode_tile_region(ctx, pool, input, out, stride, fmt, roi)
420            }
421            (None, scale) => Self::decode_tile_scaled(ctx, pool, input, out, stride, fmt, scale),
422            (Some(roi), scale) => {
423                Self::decode_tile_region_scaled(ctx, pool, input, out, stride, fmt, roi, scale)
424            }
425        }
426    }
427}
428
429/// Tile-batch helpers that return synchronous device surfaces.
430pub trait TileBatchDecodeDevice: ImageCodec {
431    /// Codec-specific context cached across tiles.
432    type Context: CodecContext;
433    /// Device surface returned by decode calls.
434    type DeviceSurface: DeviceSurface;
435
436    /// Decode one tile to the requested backend.
437    fn decode_tile_to_device<'a>(
438        ctx: &mut DecoderContext<<Self as TileBatchDecodeDevice>::Context>,
439        pool: &mut Self::Pool,
440        input: &'a [u8],
441        fmt: PixelFormat,
442        backend: BackendRequest,
443    ) -> Result<<Self as TileBatchDecodeDevice>::DeviceSurface, Self::Error>
444    where
445        Self: TileBatchDecodeSubmit<
446            Context = <Self as TileBatchDecodeDevice>::Context,
447            DeviceSurface = <Self as TileBatchDecodeDevice>::DeviceSurface,
448        >,
449    {
450        let mut session = <Self as TileBatchDecodeSubmit>::Session::default();
451        <Self as TileBatchDecodeSubmit>::submit_tile_to_device(
452            ctx,
453            &mut session,
454            pool,
455            input,
456            fmt,
457            backend,
458        )?
459        .wait()
460    }
461
462    /// Decode one tile region to the requested backend.
463    fn decode_tile_region_to_device<'a>(
464        ctx: &mut DecoderContext<<Self as TileBatchDecodeDevice>::Context>,
465        pool: &mut Self::Pool,
466        input: &'a [u8],
467        fmt: PixelFormat,
468        roi: Rect,
469        backend: BackendRequest,
470    ) -> Result<<Self as TileBatchDecodeDevice>::DeviceSurface, Self::Error>
471    where
472        Self: TileBatchDecodeSubmit<
473            Context = <Self as TileBatchDecodeDevice>::Context,
474            DeviceSurface = <Self as TileBatchDecodeDevice>::DeviceSurface,
475        >,
476    {
477        let mut session = <Self as TileBatchDecodeSubmit>::Session::default();
478        <Self as TileBatchDecodeSubmit>::submit_tile_region_to_device(
479            ctx,
480            &mut session,
481            pool,
482            input,
483            fmt,
484            roi,
485            backend,
486        )?
487        .wait()
488    }
489
490    /// Decode one tile at reduced resolution to the requested backend.
491    fn decode_tile_scaled_to_device<'a>(
492        ctx: &mut DecoderContext<<Self as TileBatchDecodeDevice>::Context>,
493        pool: &mut Self::Pool,
494        input: &'a [u8],
495        fmt: PixelFormat,
496        scale: Downscale,
497        backend: BackendRequest,
498    ) -> Result<<Self as TileBatchDecodeDevice>::DeviceSurface, Self::Error>
499    where
500        Self: TileBatchDecodeSubmit<
501            Context = <Self as TileBatchDecodeDevice>::Context,
502            DeviceSurface = <Self as TileBatchDecodeDevice>::DeviceSurface,
503        >,
504    {
505        let mut session = <Self as TileBatchDecodeSubmit>::Session::default();
506        <Self as TileBatchDecodeSubmit>::submit_tile_scaled_to_device(
507            ctx,
508            &mut session,
509            pool,
510            input,
511            fmt,
512            scale,
513            backend,
514        )?
515        .wait()
516    }
517
518    /// Decode one tile region at reduced resolution to the requested backend.
519    fn decode_tile_region_scaled_to_device<'a>(
520        ctx: &mut DecoderContext<<Self as TileBatchDecodeDevice>::Context>,
521        pool: &mut Self::Pool,
522        input: &'a [u8],
523        fmt: PixelFormat,
524        roi: Rect,
525        scale: Downscale,
526        backend: BackendRequest,
527    ) -> Result<<Self as TileBatchDecodeDevice>::DeviceSurface, Self::Error>
528    where
529        Self: TileBatchDecodeSubmit<
530            Context = <Self as TileBatchDecodeDevice>::Context,
531            DeviceSurface = <Self as TileBatchDecodeDevice>::DeviceSurface,
532        >,
533    {
534        let mut session = <Self as TileBatchDecodeSubmit>::Session::default();
535        <Self as TileBatchDecodeSubmit>::submit_tile_region_scaled_to_device(
536            ctx,
537            &mut session,
538            pool,
539            input,
540            fmt,
541            roi,
542            scale,
543            backend,
544        )?
545        .wait()
546    }
547}
548
549/// Full-tile batch helpers that decode many independent tiles to device surfaces.
550pub trait TileBatchDecodeManyDevice: ImageCodec {
551    /// Codec-specific context cached across tiles.
552    type Context: CodecContext;
553    /// Device surface returned by decode calls.
554    type DeviceSurface: DeviceSurface;
555
556    /// Decode many full tiles to the requested backend, preserving input order.
557    fn decode_tiles_to_device(
558        ctx: &mut DecoderContext<Self::Context>,
559        pool: &mut Self::Pool,
560        inputs: &[&[u8]],
561        fmt: PixelFormat,
562        backend: BackendRequest,
563    ) -> Result<Vec<Self::DeviceSurface>, Self::Error>;
564}
565
566/// Tile-batch helpers that queue device submissions.
567pub trait TileBatchDecodeSubmit: ImageCodec {
568    /// Codec-specific context cached across tiles.
569    type Context: CodecContext;
570    /// Mutable session state shared across submissions.
571    type Session: Default + Send;
572    /// Device surface returned by completed submissions.
573    type DeviceSurface: DeviceSurface;
574    /// Submission handle type.
575    type SubmittedSurface: DeviceSubmission<Output = Self::DeviceSurface, Error = Self::Error>;
576
577    /// Submit one full tile to the requested backend.
578    fn submit_tile_to_device<'a>(
579        ctx: &mut DecoderContext<Self::Context>,
580        session: &mut Self::Session,
581        pool: &mut Self::Pool,
582        input: &'a [u8],
583        fmt: PixelFormat,
584        backend: BackendRequest,
585    ) -> Result<Self::SubmittedSurface, Self::Error>;
586
587    /// Submit one tile region to the requested backend.
588    fn submit_tile_region_to_device<'a>(
589        ctx: &mut DecoderContext<Self::Context>,
590        session: &mut Self::Session,
591        pool: &mut Self::Pool,
592        input: &'a [u8],
593        fmt: PixelFormat,
594        roi: Rect,
595        backend: BackendRequest,
596    ) -> Result<Self::SubmittedSurface, Self::Error>;
597
598    /// Submit one tile at reduced resolution to the requested backend.
599    fn submit_tile_scaled_to_device<'a>(
600        ctx: &mut DecoderContext<Self::Context>,
601        session: &mut Self::Session,
602        pool: &mut Self::Pool,
603        input: &'a [u8],
604        fmt: PixelFormat,
605        scale: Downscale,
606        backend: BackendRequest,
607    ) -> Result<Self::SubmittedSurface, Self::Error>;
608
609    /// Submit one tile region at reduced resolution to the requested backend.
610    #[allow(clippy::too_many_arguments)]
611    fn submit_tile_region_scaled_to_device<'a>(
612        ctx: &mut DecoderContext<Self::Context>,
613        session: &mut Self::Session,
614        pool: &mut Self::Pool,
615        input: &'a [u8],
616        fmt: PixelFormat,
617        roi: Rect,
618        scale: Downscale,
619        backend: BackendRequest,
620    ) -> Result<Self::SubmittedSurface, Self::Error>;
621
622    /// Submit one tile for a normalized full/ROI/scaled request.
623    fn submit_tile_request_to_device<'a>(
624        ctx: &mut DecoderContext<Self::Context>,
625        session: &mut Self::Session,
626        pool: &mut Self::Pool,
627        input: &'a [u8],
628        fmt: PixelFormat,
629        backend: BackendRequest,
630        request: DecodeRequest,
631    ) -> Result<Self::SubmittedSurface, Self::Error> {
632        match (request.roi, request.scale) {
633            (None, Downscale::None) => {
634                Self::submit_tile_to_device(ctx, session, pool, input, fmt, backend)
635            }
636            (Some(roi), Downscale::None) => {
637                Self::submit_tile_region_to_device(ctx, session, pool, input, fmt, roi, backend)
638            }
639            (None, scale) => {
640                Self::submit_tile_scaled_to_device(ctx, session, pool, input, fmt, scale, backend)
641            }
642            (Some(roi), scale) => Self::submit_tile_region_scaled_to_device(
643                ctx, session, pool, input, fmt, roi, scale, backend,
644            ),
645        }
646    }
647}
648
649/// Tile payload decompression API for container codecs such as Deflate, Zstd,
650/// LZW, and uncompressed data.
651pub trait TileDecompress {
652    /// Codec-specific error type.
653    type Error: CodecError;
654    /// Caller-owned scratch pool type.
655    type Pool: ScratchPool;
656
657    /// Return the expected decoded size when the compressed payload encodes it.
658    fn expected_size(input: &[u8]) -> Result<Option<usize>, Self::Error>;
659
660    /// Decompress `input` into `out`, returning the number of bytes written.
661    fn decompress_into(
662        pool: &mut Self::Pool,
663        input: &[u8],
664        out: &mut [u8],
665    ) -> Result<usize, Self::Error>;
666}