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, ParseBoolError};
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!(i32);
158as_from_str!(ResourceIdentifier);
159as_from_str!(SafeLong);
160as_from_str!(String);
161as_from_str!(Uuid);
162
163impl FromPlain for bool {
164 type Err = ParseBoolError;
165
166 #[inline]
167 fn from_plain(s: &str) -> Result<Self, Self::Err> {
168 if s.eq_ignore_ascii_case("true") {
169 Ok(true)
170 } else if s.eq_ignore_ascii_case("false") {
171 Ok(false)
172 } else {
173 s.parse()
175 }
176 }
177}
178
179impl FromPlain for Bytes {
180 type Err = ParseBinaryError;
181
182 #[inline]
183 fn from_plain(s: &str) -> Result<Self, ParseBinaryError> {
184 let buf = STANDARD.decode(s).map_err(ParseBinaryError)?;
185 Ok(Bytes::from(buf))
186 }
187}
188
189#[derive(Debug)]
191pub struct ParseBinaryError(DecodeError);
192
193impl fmt::Display for ParseBinaryError {
194 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
195 fmt::Display::fmt(&self.0, fmt)
196 }
197}
198
199impl Error for ParseBinaryError {
200 fn source(&self) -> Option<&(dyn Error + 'static)> {
201 self.0.source()
202 }
203}
204
205impl FromPlain for DateTime<Utc> {
206 type Err = ParseError;
207
208 #[inline]
209 fn from_plain(s: &str) -> Result<DateTime<Utc>, ParseError> {
210 DateTime::parse_from_rfc3339(s).map(|t| t.with_timezone(&Utc))
211 }
212}
213
214impl FromPlain for f64 {
215 type Err = ParseFloatError;
216
217 #[inline]
218 fn from_plain(s: &str) -> Result<f64, ParseFloatError> {
219 match s {
221 "Infinity" => Ok(f64::INFINITY),
222 "-Infinity" => Ok(f64::NEG_INFINITY),
223 s => s.parse(),
224 }
225 }
226}
227
228#[derive(Debug, Default)]
230pub struct ParseEnumError(());
231
232impl ParseEnumError {
233 #[inline]
235 pub fn new() -> ParseEnumError {
236 ParseEnumError(())
237 }
238}
239
240impl fmt::Display for ParseEnumError {
241 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
242 fmt.write_str("invalid enum variant")
243 }
244}
245
246impl Error for ParseEnumError {}