ufotofu_codec/decode.rs
1#[cfg(feature = "alloc")]
2extern crate alloc;
3#[cfg(feature = "std")]
4extern crate std;
5
6use core::convert::Infallible;
7use core::future::Future;
8
9use ufotofu::{producer::FromSlice, BulkProducer};
10
11use crate::DecodeError;
12
13/// Methods for decoding a value that belongs to an *encoding relation*.
14///
15/// API contracts:
16///
17/// - The result of decoding must depend only on the decoded bytes, not on details of the producer such as when it yields or how many items it exposes at a time.
18/// - `decode` must not read any bytes beyond the end of the encoding.
19/// - For types that also implement [`Encodable`](crate::Encodable) and [`Eq`], encoding a value and then decoding it must yield a value equal to the original.
20pub trait Decodable: Sized {
21 /// Reason why decoding can fail (beyond an unexpected end of input or a producer error).
22 type ErrorReason;
23
24 /// Decodes the bytes produced by the given producer into a `Self`, or yields an error if the producer does not produce a valid encoding.
25 fn decode<P>(
26 producer: &mut P,
27 ) -> impl Future<Output = Result<Self, DecodeError<P::Final, P::Error, Self::ErrorReason>>>
28 where
29 P: BulkProducer<Item = u8>,
30 Self: Sized;
31
32 /// Decodes from a slice instead of a producer.
33 fn decode_from_slice(
34 enc: &[u8],
35 ) -> impl Future<Output = Result<Self, DecodeError<(), Infallible, Self::ErrorReason>>> {
36 async { Self::decode(&mut FromSlice::new(enc)).await }
37 }
38}
39
40/// Decoding for an *encoding relation* with a one-to-one mapping between values and their codes (i.e., the relation is a [bijection](https://en.wikipedia.org/wiki/Bijection)).
41///
42/// This may specialise an arbitrary encoding relation to implement a canonic subset.
43///
44/// API contracts:
45///
46/// - Two nonequal codes must not decode to the same value with `decode_canonic`.
47/// - Any code that decodes via `decode_canonic` must also decode via `decode` to the same value.
48/// - For types that also implement [`Encodable`](crate::Encodable) and [`Eq`], if canonically decoding a bytestring suceedes, then reencoding the resulting value must result in the original bytestring.
49///
50/// There is no corresponding `EncodableCanonic` trait, because `Encodable` already fulfils the dual requirement of two nonequal values yielding nonequal codes.
51pub trait DecodableCanonic: Decodable {
52 /// The type for reporting that the bytestring to decode was not a valid canonic encoding of any value of type `Self`.
53 ///
54 /// Typically contains at least as much information as [`Self::ErrorReason`](Decodable::ErrorReason). If the encoding relation implemented by [`Decodable`] is already canonic, then [`ErrorCanonic`](DecodableCanonic::ErrorCanonic) should be equal to [`Self::ErrorReason`](Decodable::ErrorReason).
55 type ErrorCanonic: From<Self::ErrorReason>;
56
57 /// Decodes the bytes produced by the given producer into a `Self`, and errors if the input encoding is not the canonical one.
58 fn decode_canonic<P>(
59 producer: &mut P,
60 ) -> impl Future<Output = Result<Self, DecodeError<P::Final, P::Error, Self::ErrorCanonic>>>
61 where
62 P: BulkProducer<Item = u8>,
63 Self: Sized;
64
65 /// Decodes from a slice instead of a producer, and errors if the input encoding is not the canonical one.
66 fn decode_canonic_from_slice(
67 enc: &[u8],
68 ) -> impl Future<Output = Result<Self, DecodeError<(), Infallible, Self::ErrorCanonic>>> {
69 async { Self::decode_canonic(&mut FromSlice::new(enc)).await }
70 }
71}
72
73/// A decodable that introduces no asynchrony beyond that of `.await`ing the producer. This is essentially a marker trait by which to tell other programmers about this property. As a practical benefit, the default methods of this trait allow for convenient synchronous decoding by internally using producers that are known to never block.
74pub trait DecodableSync: Decodable {
75 /// Synchronously decodes from a slice instead of a producer.
76 fn sync_decode_from_slice(
77 enc: &[u8],
78 ) -> Result<Self, DecodeError<(), Infallible, Self::ErrorReason>> {
79 pollster::block_on(Self::decode_from_slice(enc))
80 }
81
82 /// Synchronously and absolutely decodes from a slice instead of a producer, and errors if the input encoding is not the canonical one.
83 fn sync_decode_canonic_from_slice(
84 enc: &[u8],
85 ) -> Result<Self, DecodeError<(), Infallible, Self::ErrorCanonic>>
86 where
87 Self: DecodableCanonic,
88 {
89 pollster::block_on(Self::decode_canonic_from_slice(enc))
90 }
91}