1use base64::display::Base64Display;
18use base64::engine::general_purpose::STANDARD;
19use base64::{DecodeError, Engine};
20use bytes::Bytes;
21use chrono::format::{Fixed, Item, ParseError};
22use chrono::{DateTime, Utc};
23use std::error::Error;
24use std::f64;
25use std::fmt;
26use std::iter;
27use std::num::ParseFloatError;
28use std::str::FromStr;
29use uuid::Uuid;
30
31use crate::{BearerToken, ResourceIdentifier, SafeLong};
32
33pub trait Plain {
35 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
37}
38
39impl<T> Plain for &T
40where
41 T: ?Sized + Plain,
42{
43 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
44 Plain::fmt(&**self, fmt)
45 }
46}
47
48macro_rules! as_display {
49 ($t:ty) => {
50 impl Plain for $t {
51 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
52 fmt::Display::fmt(self, fmt)
53 }
54 }
55 };
56}
57
58as_display!(bool);
59as_display!(i32);
60as_display!(ResourceIdentifier);
61as_display!(SafeLong);
62as_display!(str);
63as_display!(String);
64as_display!(Uuid);
65
66impl Plain for BearerToken {
67 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
68 fmt::Display::fmt(self.as_str(), fmt)
69 }
70}
71
72impl Plain for DateTime<Utc> {
73 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
74 fmt::Display::fmt(
75 &self.format_with_items(iter::once(Item::Fixed(Fixed::RFC3339))),
76 fmt,
77 )
78 }
79}
80
81impl Plain for f64 {
82 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
83 if *self == f64::INFINITY {
85 fmt::Display::fmt("Infinity", fmt)
86 } else if *self == f64::NEG_INFINITY {
87 fmt::Display::fmt("-Infinity", fmt)
88 } else {
89 fmt::Display::fmt(self, fmt)
90 }
91 }
92}
93
94impl Plain for [u8] {
95 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
96 fmt::Display::fmt(&Base64Display::new(self, &STANDARD), fmt)
97 }
98}
99
100impl Plain for Bytes {
101 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
102 Plain::fmt(&**self, fmt)
103 }
104}
105
106pub trait ToPlain {
110 fn to_plain(&self) -> String;
112}
113
114impl<T> ToPlain for T
115where
116 T: ?Sized + Plain,
117{
118 fn to_plain(&self) -> String {
119 struct Adaptor<T>(T);
120
121 impl<T> fmt::Display for Adaptor<T>
122 where
123 T: Plain,
124 {
125 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
126 Plain::fmt(&self.0, fmt)
127 }
128 }
129
130 Adaptor(self).to_string()
131 }
132}
133
134pub trait FromPlain: Sized {
136 type Err;
138
139 fn from_plain(s: &str) -> Result<Self, Self::Err>;
141}
142
143macro_rules! as_from_str {
144 ($t:ty) => {
145 impl FromPlain for $t {
146 type Err = <$t as FromStr>::Err;
147
148 #[inline]
149 fn from_plain(s: &str) -> Result<Self, Self::Err> {
150 s.parse()
151 }
152 }
153 };
154}
155
156as_from_str!(BearerToken);
157as_from_str!(bool);
158as_from_str!(i32);
159as_from_str!(ResourceIdentifier);
160as_from_str!(SafeLong);
161as_from_str!(String);
162as_from_str!(Uuid);
163
164impl FromPlain for Bytes {
165 type Err = ParseBinaryError;
166
167 #[inline]
168 fn from_plain(s: &str) -> Result<Self, ParseBinaryError> {
169 let buf = STANDARD.decode(s).map_err(ParseBinaryError)?;
170 Ok(Bytes::from(buf))
171 }
172}
173
174#[derive(Debug)]
176pub struct ParseBinaryError(DecodeError);
177
178impl fmt::Display for ParseBinaryError {
179 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
180 fmt::Display::fmt(&self.0, fmt)
181 }
182}
183
184impl Error for ParseBinaryError {
185 fn source(&self) -> Option<&(dyn Error + 'static)> {
186 self.0.source()
187 }
188}
189
190impl FromPlain for DateTime<Utc> {
191 type Err = ParseError;
192
193 #[inline]
194 fn from_plain(s: &str) -> Result<DateTime<Utc>, ParseError> {
195 DateTime::parse_from_rfc3339(s).map(|t| t.with_timezone(&Utc))
196 }
197}
198
199impl FromPlain for f64 {
200 type Err = ParseFloatError;
201
202 #[inline]
203 fn from_plain(s: &str) -> Result<f64, ParseFloatError> {
204 match s {
206 "Infinity" => Ok(f64::INFINITY),
207 "-Infinity" => Ok(f64::NEG_INFINITY),
208 s => s.parse(),
209 }
210 }
211}
212
213#[derive(Debug, Default)]
215pub struct ParseEnumError(());
216
217impl ParseEnumError {
218 #[inline]
220 pub fn new() -> ParseEnumError {
221 ParseEnumError(())
222 }
223}
224
225impl fmt::Display for ParseEnumError {
226 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
227 fmt.write_str("invalid enum variant")
228 }
229}
230
231impl Error for ParseEnumError {}