format_ende/
lib.rs

1//! This crate provides the `FormatInfo`, `FormatEncoder`, and `FormatDecoder` traits.
2//! These traits allow to encode/decode data from/to a generic format.
3//!
4//! # Example
5//! ```
6//! use format_ende::FormatInfo;
7//! use format_ende::FormatEncoder;
8//!
9//! /// Print given value encoded with the given encoder
10//! fn print<E, V>(encoder: &mut E, value: &V) where
11//!     E: FormatInfo,
12//!     E: FormatEncoder<V>,
13//!     E::EncodeError: std::fmt::Debug,
14//! {
15//!     println!(
16//!         "{} as {}:",
17//!         std::any::type_name::<V>(),
18//!         encoder.file_extension()
19//!     );
20//!     let mut stdout = std::io::stdout();
21//!     encoder.encode(&mut stdout, value).unwrap();
22//!     println!();
23//! }
24//! ```
25
26use std::error::Error;
27use std::io;
28
29/// Information about a specific format, such as its file extension
30pub trait FormatInfo {
31    /// Returns the file extension associated with this format (without the dot)
32    fn file_extension(&self) -> &str;
33}
34
35/// A trait for encoding values of type `V` into a specific format
36pub trait FormatEncoder<V: ?Sized> {
37    /// The error type that can occur during encoding
38    type EncodeError;
39
40    /// Encodes the given value into the provided writer
41    fn encode(&mut self, writer: impl io::Write, value: &V) -> Result<(), Self::EncodeError>;
42}
43
44/// A trait for decoding values of type `V` from a specific format
45pub trait FormatDecoder<V> {
46    /// The error type that can occur during decoding
47    type DecodeError;
48
49    /// Decodes a value from the provided reader
50    fn decode(&mut self, reader: impl io::Read) -> Result<V, Self::DecodeError>;
51}
52
53/// A trait object version of `FormatEncoder` for dynamic dispatch
54pub trait FormatEncoderDyn<V: ?Sized, E = Box<dyn Error>> {
55    /// Encodes the given value into the provided writer
56    fn encode_dyn(&mut self, writer: &mut dyn io::Write, value: &V) -> Result<(), E>;
57}
58
59/// A trait object version of `FormatDecoder` for dynamic dispatch
60pub trait FormatDecoderDyn<V, E = Box<dyn Error>> {
61    /// Decodes a value from the provided reader
62    fn decode_dyn(&mut self, reader: &mut dyn io::Read) -> Result<V, E>;
63}
64
65impl<T, V> FormatEncoder<V> for &mut T
66where
67    T: ?Sized,
68    V: ?Sized,
69    T: FormatEncoder<V>,
70{
71    type EncodeError = T::EncodeError;
72
73    fn encode(&mut self, writer: impl io::Write, value: &V) -> Result<(), Self::EncodeError> {
74        T::encode(self, writer, value)
75    }
76}
77
78impl<T, V> FormatEncoder<V> for Box<T>
79where
80    T: ?Sized,
81    V: ?Sized,
82    T: FormatEncoder<V>,
83{
84    type EncodeError = T::EncodeError;
85
86    fn encode(&mut self, writer: impl io::Write, value: &V) -> Result<(), Self::EncodeError> {
87        T::encode(self, writer, value)
88    }
89}
90
91impl<T, V> FormatDecoder<V> for &mut T
92where
93    T: ?Sized,
94    T: FormatDecoder<V>,
95{
96    type DecodeError = T::DecodeError;
97
98    fn decode(&mut self, reader: impl io::Read) -> Result<V, Self::DecodeError> {
99        T::decode(self, reader)
100    }
101}
102
103impl<T, V> FormatDecoder<V> for Box<T>
104where
105    T: ?Sized,
106    T: FormatDecoder<V>,
107{
108    type DecodeError = T::DecodeError;
109
110    fn decode(&mut self, reader: impl io::Read) -> Result<V, Self::DecodeError> {
111        T::decode(self, reader)
112    }
113}
114
115impl<T, V, E> FormatEncoderDyn<V, E> for T
116where
117    T: FormatEncoder<V> + ?Sized,
118    V: ?Sized,
119    T::EncodeError: Into<E>,
120{
121    fn encode_dyn(&mut self, writer: &mut dyn io::Write, value: &V) -> Result<(), E> {
122        self.encode(writer, value).map_err(Into::into)
123    }
124}
125
126impl<T, V, E> FormatDecoderDyn<V, E> for T
127where
128    T: FormatDecoder<V> + ?Sized,
129    T::DecodeError: Into<E>,
130{
131    fn decode_dyn(&mut self, reader: &mut dyn io::Read) -> Result<V, E> {
132        self.decode(reader).map_err(Into::into)
133    }
134}