google_cloud_bigquery/http/
mod.rs

1use std::fmt::Display;
2use std::str::FromStr;
3
4use serde::{de, Deserialize, Deserializer};
5use serde_json::Value;
6
7pub mod bigquery_client;
8pub mod bigquery_dataset_client;
9pub mod bigquery_job_client;
10pub mod bigquery_model_client;
11pub mod bigquery_routine_client;
12pub mod bigquery_row_access_policy_client;
13pub mod bigquery_table_client;
14pub mod bigquery_tabledata_client;
15pub mod dataset;
16pub mod error;
17pub mod job;
18pub mod model;
19pub mod query;
20pub mod routine;
21pub mod row_access_policy;
22pub mod table;
23pub mod tabledata;
24pub mod types;
25
26fn from_str_option<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error>
27where
28    T: FromStr,
29    T::Err: Display,
30    D: Deserializer<'de>,
31{
32    let s: Result<Value, _> = Deserialize::deserialize(deserializer);
33    match s {
34        Ok(Value::String(s)) => T::from_str(&s).map_err(de::Error::custom).map(Some),
35        Ok(_) => Err(de::Error::custom("Incorrect type")),
36        Err(_) => Ok(None),
37    }
38}
39
40pub fn from_str<'de, T, D>(deserializer: D) -> Result<T, D::Error>
41where
42    T: FromStr,
43    T::Err: Display,
44    D: de::Deserializer<'de>,
45{
46    let s = String::deserialize(deserializer)?;
47    T::from_str(&s).map_err(de::Error::custom)
48}
49
50fn into_str<T, S>(value: T, s: S) -> Result<S::Ok, S::Error>
51where
52    T: ToString,
53    S: serde::Serializer,
54{
55    s.serialize_str(&value.to_string())
56}
57
58fn from_str_vec_option<'de, T, D>(deserializer: D) -> Result<Option<Vec<T>>, D::Error>
59where
60    T: FromStr,
61    T::Err: Display,
62    D: Deserializer<'de>,
63{
64    let s: Result<Value, _> = Deserialize::deserialize(deserializer);
65    match s {
66        Ok(Value::Array(vec)) => {
67            let mut result = Vec::with_capacity(vec.len());
68            for v in vec {
69                let v = match v {
70                    Value::String(s) => T::from_str(&s).map_err(de::Error::custom)?,
71                    _ => return Err(de::Error::custom("Incorrect type")),
72                };
73                result.push(v);
74            }
75            Ok(Some(result))
76        }
77        Ok(_) => Err(de::Error::custom("Incorrect type")),
78        Err(_) => Ok(None),
79    }
80}
81
82fn from_str_vec<'de, T, D>(deserializer: D) -> Result<Vec<T>, D::Error>
83where
84    T: FromStr,
85    T::Err: Display,
86    D: Deserializer<'de>,
87{
88    let vec: Vec<String> = Vec::deserialize(deserializer)?;
89    let mut result = Vec::with_capacity(vec.len());
90    for v in vec {
91        result.push(T::from_str(&v).map_err(de::Error::custom)?);
92    }
93    Ok(result)
94}
95
96#[cfg(test)]
97mod test {
98
99    #[derive(Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize, Debug, Default)]
100    #[serde(rename_all = "camelCase")]
101    struct Test {
102        #[serde(default, deserialize_with = "crate::http::from_str_vec_option")]
103        pub field: Option<Vec<i64>>,
104    }
105
106    #[test]
107    fn test_from_str_vec_option() {
108        let value: Test = serde_json::from_str(r#"{"field": ["100", "200"]}"#).unwrap();
109        let record = value.field.unwrap();
110        assert_eq!(vec![100, 200], record);
111
112        let value: Test = serde_json::from_str(r#"{}"#).unwrap();
113        assert!(value.field.is_none());
114    }
115
116    #[derive(Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize, Debug, Default)]
117    #[serde(rename_all = "camelCase")]
118    struct Test2 {
119        #[serde(deserialize_with = "crate::http::from_str_vec")]
120        pub field: Vec<i64>,
121    }
122
123    #[test]
124    fn test_from_str_vec() {
125        let value: Test2 = serde_json::from_str(r#"{"field": ["100", "200"]}"#).unwrap();
126        assert_eq!(vec![100, 200], value.field);
127        let result = serde_json::from_str::<Test2>(r#"{}"#);
128        assert!(result.is_err())
129    }
130}