1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
use serde::{
	Deserialize,
	de::{Deserializer, Error as DeserializeError, Unexpected}
};
use std::sync::Mutex;
use tokio::join;

const FROM_STR_ERR: &str =
	"string value that can be parsed into other values";

pub(crate) fn from_str<'d, T, D>(deserializer: D) -> Result<T, D::Error>
		where T: std::str::FromStr,
			D: Deserializer<'d> {
	let string = <&'d str>::deserialize(deserializer)?;
	T::from_str(&string).map_err(|_| DeserializeError::invalid_value(
		Unexpected::Str(string), &FROM_STR_ERR))
}

pub(crate) fn from_str_opt<'d, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
		where T: std::str::FromStr,
			D: Deserializer<'d> {
	let string = Option::<&'d str>::deserialize(deserializer)?;
	Ok(match string {
		Some(string) => Some(T::from_str(&string).map_err(|_| DeserializeError
			::invalid_value(Unexpected::Str(string), &FROM_STR_ERR))?),
		None => None
	})
}

pub(crate) macro join_first($($future:expr),*) {{
	let result = Mutex::new(None);
	join!($(async {
		let output = $future.await;
		if let ref mut result @ None = *result.lock().unwrap() {
			*result = Some(output)
		}
	}),*);
	result.into_inner().unwrap().unwrap()
}}