codee/string/
option.rs

1use crate::{Decoder, Encoder};
2
3/// Wraps a string codec that encodes `T` to create a codec that encodes `Option<T>`.
4///
5/// Example:
6///
7/// ```
8/// # use codee::{Encoder, Decoder};
9/// # use codee::string::{OptionCodec, FromToStringCodec};
10/// #
11/// let original_value = Some(4);
12/// let encoded = OptionCodec::<FromToStringCodec>::encode(&original_value).unwrap();
13/// let decoded = OptionCodec::<FromToStringCodec>::decode(&encoded).unwrap();
14///
15/// assert_eq!(decoded, original_value);
16/// ```
17pub struct OptionCodec<C>(C);
18
19impl<T, E> Encoder<Option<T>> for OptionCodec<E>
20where
21    E: Encoder<T, Encoded = String>,
22{
23    type Error = E::Error;
24    type Encoded = String;
25
26    fn encode(val: &Option<T>) -> Result<String, Self::Error> {
27        match val {
28            Some(val) => Ok(format!("~<|Some|>~{}", E::encode(val)?)),
29            None => Ok("~<|None|>~".to_owned()),
30        }
31    }
32}
33
34impl<T, D> Decoder<Option<T>> for OptionCodec<D>
35where
36    D: Decoder<T, Encoded = str>,
37{
38    type Error = D::Error;
39    type Encoded = str;
40
41    fn decode(str: &Self::Encoded) -> Result<Option<T>, Self::Error> {
42        str.strip_prefix("~<|Some|>~")
43            .map(|v| D::decode(v))
44            .transpose()
45    }
46}