1#![deny(
7 clippy::all,
8 clippy::cargo,
9 missing_docs,
10 missing_debug_implementations,
11 rust_2018_idioms,
12 unreachable_pub
13)]
14#![allow(clippy::multiple_crate_versions)]
16
17use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
18use std::num::TryFromIntError;
19use std::path::PathBuf;
20use std::{collections::HashMap, net::IpAddr};
21
22pub trait FromNative<N>: Sized {
37 fn from_native(value: N) -> Self;
39}
40
41pub trait IntoProto<P>: Sized {
56 fn into_proto(self) -> P;
58}
59
60pub trait TryFromProto<P>: Sized {
74 fn try_from_proto(value: P) -> Result<Self, ProstConvertError>;
76}
77
78pub trait TryIntoNative<N>: Sized {
87 fn try_into_native(self) -> Result<N, ProstConvertError>;
89}
90
91#[allow(missing_docs)]
98#[derive(thiserror::Error, Debug)]
99pub enum ProstConvertError {
100 #[error("prost struct miss a required field")]
101 MissingRequiredField,
102 #[error("infallible")]
103 Infallible(#[from] std::convert::Infallible),
104 #[error("invalid ip address")]
105 AddrParseError(#[from] std::net::AddrParseError),
106 #[error("invalid uuid address")]
107 UuidEroor(#[from] uuid::Error),
108 #[error("int convertion error")]
109 TryFromIntError(#[from] TryFromIntError),
110 #[error("try to parse a type and failed")]
111 TypeParseError(#[from] anyhow::Error),
112}
113
114impl<T, U> TryIntoNative<U> for T
120where
121 U: TryFromProto<T>,
122{
123 fn try_into_native(self) -> Result<U, ProstConvertError> {
124 U::try_from_proto(self)
125 }
126}
127
128impl<T, U> IntoProto<U> for T
130where
131 U: FromNative<T>,
132{
133 fn into_proto(self) -> U {
134 U::from_native(self)
135 }
136}
137
138impl<T, U> TryFromProto<Option<U>> for T
141where
142 T: TryFromProto<U>,
143{
144 fn try_from_proto(value: Option<U>) -> Result<Self, ProstConvertError> {
145 match value {
146 Some(value) => value.try_into_native(),
147 None => Err(ProstConvertError::MissingRequiredField),
148 }
149 }
150}
151
152impl<T, U> FromNative<U> for Option<T>
159where
160 T: FromNative<U>,
161{
162 fn from_native(value: U) -> Self {
163 Some(value.into_proto())
164 }
165}
166
167impl<T, U> TryFromProto<Vec<U>> for Vec<T>
169where
170 T: TryFromProto<U>,
171{
172 fn try_from_proto(value: Vec<U>) -> Result<Self, ProstConvertError> {
173 let mut native = Vec::with_capacity(value.len());
174 for element in value {
175 native.push(element.try_into_native()?)
176 }
177 Ok(native)
178 }
179}
180
181impl<T, U> FromNative<Vec<U>> for Vec<T>
183where
184 T: FromNative<U>,
185{
186 fn from_native(value: Vec<U>) -> Self {
187 let mut proto = Vec::new();
188 for element in value {
189 proto.push(element.into_proto());
190 }
191 proto
192 }
193}
194
195macro_rules! impl_scalar {
198 ( $($t:ty),* ) => {
199 $(
200 impl TryFromProto<$t> for $t {
201 fn try_from_proto(value: $t) -> Result<Self, ProstConvertError> {
202 Ok(value)
203 }
204 }
205
206 impl FromNative<$t> for $t {
207 fn from_native(value: $t) -> Self {
208 value
209 }
210 }
211 )*
212
213 };
214}
215
216impl_scalar!(f32, f64, i32, i64, u32, u64, bool, String, Vec<u8>);
217
218macro_rules! impl_map {
219 ( $($t:ty),* ) => {
220
221 $(
222 impl<T, U> TryFromProto<HashMap<$t, U>> for HashMap<$t, T>
223 where
224 T: TryFromProto<U>,
225 {
226 fn try_from_proto(value: HashMap<$t, U>) -> Result<Self, ProstConvertError> {
227 let mut native = HashMap::with_capacity(value.len());
228 for (key, value) in value {
229 native.insert(key, value.try_into_native()?);
230 }
231 Ok(native)
232 }
233 }
234
235 impl<T, U> FromNative<HashMap<$t, U>> for HashMap<$t, T>
236 where
237 T: FromNative<U>,
238 {
239 fn from_native(value: HashMap<$t, U>) -> Self {
240 let mut proto = HashMap::with_capacity(value.len());
241 for (key, value) in value {
242 proto.insert(key, value.into_proto());
243 }
244 proto
245 }
246 }
247 )*
248 };
249}
250
251impl_map!(i32, i64, u32, u64, bool, String);
254
255impl FromNative<PathBuf> for String {
256 fn from_native(value: PathBuf) -> Self {
257 value.to_string_lossy().into_owned()
258 }
259}
260
261impl TryFromProto<String> for PathBuf {
262 fn try_from_proto(value: String) -> Result<Self, ProstConvertError> {
263 Ok(value.parse()?)
264 }
265}
266
267impl FromNative<IpAddr> for String {
268 fn from_native(value: IpAddr) -> Self {
269 value.to_string()
270 }
271}
272
273impl TryFromProto<String> for IpAddr {
274 fn try_from_proto(value: String) -> Result<Self, ProstConvertError> {
275 Ok(value.parse()?)
276 }
277}
278
279impl FromNative<Ipv4Addr> for String {
280 fn from_native(value: Ipv4Addr) -> Self {
281 value.to_string()
282 }
283}
284
285impl TryFromProto<String> for Ipv4Addr {
286 fn try_from_proto(value: String) -> Result<Self, ProstConvertError> {
287 Ok(value.parse()?)
288 }
289}
290
291impl FromNative<Ipv6Addr> for String {
292 fn from_native(value: Ipv6Addr) -> Self {
293 value.to_string()
294 }
295}
296
297impl TryFromProto<String> for Ipv6Addr {
298 fn try_from_proto(value: String) -> Result<Self, ProstConvertError> {
299 Ok(value.parse()?)
300 }
301}
302
303impl FromNative<SocketAddr> for String {
304 fn from_native(value: SocketAddr) -> Self {
305 value.to_string()
306 }
307}
308
309impl TryFromProto<String> for SocketAddr {
310 fn try_from_proto(value: String) -> Result<Self, ProstConvertError> {
311 Ok(value.parse()?)
312 }
313}
314
315impl FromNative<()> for () {
316 fn from_native(_: ()) -> Self {}
317}
318
319impl TryFromProto<()> for () {
320 fn try_from_proto(_: ()) -> Result<Self, ProstConvertError> {
321 Ok(())
322 }
323}
324
325impl TryFromProto<u32> for u16 {
327 fn try_from_proto(value: u32) -> Result<Self, ProstConvertError> {
328 Ok(value.try_into()?)
329 }
330}
331
332impl FromNative<u16> for u32 {
333 fn from_native(value: u16) -> Self {
334 value.into()
335 }
336}
337
338impl TryFromProto<u32> for u8 {
340 fn try_from_proto(value: u32) -> Result<Self, ProstConvertError> {
341 Ok(value.try_into()?)
342 }
343}
344
345impl FromNative<u8> for u32 {
346 fn from_native(value: u8) -> Self {
347 value.into()
348 }
349}
350
351impl TryFromProto<i32> for i16 {
353 fn try_from_proto(value: i32) -> Result<Self, ProstConvertError> {
354 Ok(value.try_into()?)
355 }
356}
357
358impl FromNative<i16> for i32 {
359 fn from_native(value: i16) -> Self {
360 value.into()
361 }
362}
363
364impl TryFromProto<i32> for i8 {
366 fn try_from_proto(value: i32) -> Result<Self, ProstConvertError> {
367 Ok(value.try_into()?)
368 }
369}
370
371impl FromNative<i8> for i32 {
372 fn from_native(value: i8) -> Self {
373 value.into()
374 }
375}
376
377impl FromNative<uuid::Uuid> for String {
380 fn from_native(value: uuid::Uuid) -> Self {
381 value.to_string()
382 }
383}
384
385impl TryFromProto<String> for uuid::Uuid {
386 fn try_from_proto(value: String) -> Result<Self, ProstConvertError> {
387 Ok(value.parse()?)
388 }
389}
390
391#[cfg(feature = "prost-convert-derive")]
398#[doc(hidden)]
399pub use prost_convert_derive::ProstConvert;