tushare_api/
basic_types.rs

1//! Basic Rust type implementations for FromTushareValue and FromOptionalTushareValue traits
2//!
3//! This module provides implementations of the conversion traits for all standard Rust primitive types.
4
5use serde_json::Value;
6use crate::error::TushareError;
7use crate::traits::{FromTushareValue, FromOptionalTushareValue};
8
9// =============================================================================
10// FromTushareValue implementations for basic types
11// =============================================================================
12
13impl FromTushareValue for String {
14    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
15        match value {
16            Value::String(s) => Ok(s.clone()),
17            Value::Number(n) => Ok(n.to_string()),
18            Value::Bool(b) => Ok(b.to_string()),
19            Value::Null => Ok(String::new()),
20            _ => Err(TushareError::ParseError(format!(
21                "Cannot convert {:?} to String", value
22            ))),
23        }
24    }
25}
26
27impl FromTushareValue for f64 {
28    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
29        match value {
30            Value::Number(n) => n.as_f64().ok_or_else(|| {
31                TushareError::ParseError(format!("Cannot convert {:?} to f64", n))
32            }),
33            Value::String(s) => s.parse().map_err(|_| {
34                TushareError::ParseError(format!("Cannot parse '{}' as f64", s))
35            }),
36            _ => Err(TushareError::ParseError(format!(
37                "Cannot convert {:?} to f64", value
38            ))),
39        }
40    }
41}
42
43impl FromTushareValue for f32 {
44    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
45        match value {
46            Value::Number(n) => n.as_f64().and_then(|f| {
47                if f.is_finite() && f >= f32::MIN as f64 && f <= f32::MAX as f64 {
48                    Some(f as f32)
49                } else {
50                    None
51                }
52            }).ok_or_else(|| {
53                TushareError::ParseError(format!("Cannot convert {:?} to f32", n))
54            }),
55            Value::String(s) => s.parse().map_err(|_| {
56                TushareError::ParseError(format!("Cannot parse '{}' as f32", s))
57            }),
58            _ => Err(TushareError::ParseError(format!(
59                "Cannot convert {:?} to f32", value
60            ))),
61        }
62    }
63}
64
65impl FromTushareValue for i64 {
66    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
67        match value {
68            Value::Number(n) => n.as_i64().ok_or_else(|| {
69                TushareError::ParseError(format!("Cannot convert {:?} to i64", n))
70            }),
71            Value::String(s) => s.parse().map_err(|_| {
72                TushareError::ParseError(format!("Cannot parse '{}' as i64", s))
73            }),
74            _ => Err(TushareError::ParseError(format!(
75                "Cannot convert {:?} to i64", value
76            ))),
77        }
78    }
79}
80
81impl FromTushareValue for i32 {
82    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
83        match value {
84            Value::Number(n) => n.as_i64().and_then(|i| {
85                if i >= i32::MIN as i64 && i <= i32::MAX as i64 {
86                    Some(i as i32)
87                } else {
88                    None
89                }
90            }).ok_or_else(|| {
91                TushareError::ParseError(format!("Cannot convert {:?} to i32", n))
92            }),
93            Value::String(s) => s.parse().map_err(|_| {
94                TushareError::ParseError(format!("Cannot parse '{}' as i32", s))
95            }),
96            _ => Err(TushareError::ParseError(format!(
97                "Cannot convert {:?} to i32", value
98            ))),
99        }
100    }
101}
102
103impl FromTushareValue for i16 {
104    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
105        match value {
106            Value::Number(n) => n.as_i64().and_then(|i| {
107                if i >= i16::MIN as i64 && i <= i16::MAX as i64 {
108                    Some(i as i16)
109                } else {
110                    None
111                }
112            }).ok_or_else(|| {
113                TushareError::ParseError(format!("Cannot convert {:?} to i16", n))
114            }),
115            Value::String(s) => s.parse().map_err(|_| {
116                TushareError::ParseError(format!("Cannot parse '{}' as i16", s))
117            }),
118            _ => Err(TushareError::ParseError(format!(
119                "Cannot convert {:?} to i16", value
120            ))),
121        }
122    }
123}
124
125impl FromTushareValue for i8 {
126    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
127        match value {
128            Value::Number(n) => n.as_i64().and_then(|i| {
129                if i >= i8::MIN as i64 && i <= i8::MAX as i64 {
130                    Some(i as i8)
131                } else {
132                    None
133                }
134            }).ok_or_else(|| {
135                TushareError::ParseError(format!("Cannot convert {:?} to i8", n))
136            }),
137            Value::String(s) => s.parse().map_err(|_| {
138                TushareError::ParseError(format!("Cannot parse '{}' as i8", s))
139            }),
140            _ => Err(TushareError::ParseError(format!(
141                "Cannot convert {:?} to i8", value
142            ))),
143        }
144    }
145}
146
147impl FromTushareValue for u64 {
148    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
149        match value {
150            Value::Number(n) => n.as_u64().ok_or_else(|| {
151                TushareError::ParseError(format!("Cannot convert {:?} to u64", n))
152            }),
153            Value::String(s) => s.parse().map_err(|_| {
154                TushareError::ParseError(format!("Cannot parse '{}' as u64", s))
155            }),
156            _ => Err(TushareError::ParseError(format!(
157                "Cannot convert {:?} to u64", value
158            ))),
159        }
160    }
161}
162
163impl FromTushareValue for u32 {
164    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
165        match value {
166            Value::Number(n) => n.as_u64().and_then(|u| {
167                if u <= u32::MAX as u64 {
168                    Some(u as u32)
169                } else {
170                    None
171                }
172            }).ok_or_else(|| {
173                TushareError::ParseError(format!("Cannot convert {:?} to u32", n))
174            }),
175            Value::String(s) => s.parse().map_err(|_| {
176                TushareError::ParseError(format!("Cannot parse '{}' as u32", s))
177            }),
178            _ => Err(TushareError::ParseError(format!(
179                "Cannot convert {:?} to u32", value
180            ))),
181        }
182    }
183}
184
185impl FromTushareValue for u16 {
186    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
187        match value {
188            Value::Number(n) => n.as_u64().and_then(|u| {
189                if u <= u16::MAX as u64 {
190                    Some(u as u16)
191                } else {
192                    None
193                }
194            }).ok_or_else(|| {
195                TushareError::ParseError(format!("Cannot convert {:?} to u16", n))
196            }),
197            Value::String(s) => s.parse().map_err(|_| {
198                TushareError::ParseError(format!("Cannot parse '{}' as u16", s))
199            }),
200            _ => Err(TushareError::ParseError(format!(
201                "Cannot convert {:?} to u16", value
202            ))),
203        }
204    }
205}
206
207impl FromTushareValue for u8 {
208    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
209        match value {
210            Value::Number(n) => n.as_u64().and_then(|u| {
211                if u <= u8::MAX as u64 {
212                    Some(u as u8)
213                } else {
214                    None
215                }
216            }).ok_or_else(|| {
217                TushareError::ParseError(format!("Cannot convert {:?} to u8", n))
218            }),
219            Value::String(s) => s.parse().map_err(|_| {
220                TushareError::ParseError(format!("Cannot parse '{}' as u8", s))
221            }),
222            _ => Err(TushareError::ParseError(format!(
223                "Cannot convert {:?} to u8", value
224            ))),
225        }
226    }
227}
228
229impl FromTushareValue for usize {
230    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
231        match value {
232            Value::Number(n) => n.as_u64().and_then(|u| {
233                if u <= usize::MAX as u64 {
234                    Some(u as usize)
235                } else {
236                    None
237                }
238            }).ok_or_else(|| {
239                TushareError::ParseError(format!("Cannot convert {:?} to usize", n))
240            }),
241            Value::String(s) => s.parse().map_err(|_| {
242                TushareError::ParseError(format!("Cannot parse '{}' as usize", s))
243            }),
244            _ => Err(TushareError::ParseError(format!(
245                "Cannot convert {:?} to usize", value
246            ))),
247        }
248    }
249}
250
251impl FromTushareValue for isize {
252    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
253        match value {
254            Value::Number(n) => n.as_i64().and_then(|i| {
255                if i >= isize::MIN as i64 && i <= isize::MAX as i64 {
256                    Some(i as isize)
257                } else {
258                    None
259                }
260            }).ok_or_else(|| {
261                TushareError::ParseError(format!("Cannot convert {:?} to isize", n))
262            }),
263            Value::String(s) => s.parse().map_err(|_| {
264                TushareError::ParseError(format!("Cannot parse '{}' as isize", s))
265            }),
266            _ => Err(TushareError::ParseError(format!(
267                "Cannot convert {:?} to isize", value
268            ))),
269        }
270    }
271}
272
273impl FromTushareValue for bool {
274    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
275        match value {
276            Value::Bool(b) => Ok(*b),
277            Value::String(s) => match s.to_lowercase().as_str() {
278                "true" | "1" | "yes" | "y" => Ok(true),
279                "false" | "0" | "no" | "n" | "" => Ok(false),
280                _ => Err(TushareError::ParseError(format!(
281                    "Cannot parse '{}' as bool", s
282                ))),
283            },
284            Value::Number(n) => {
285                if let Some(i) = n.as_i64() {
286                    Ok(i != 0)
287                } else if let Some(f) = n.as_f64() {
288                    Ok(f != 0.0)
289                } else {
290                    Err(TushareError::ParseError(format!(
291                        "Cannot convert {:?} to bool", n
292                    )))
293                }
294            },
295            _ => Err(TushareError::ParseError(format!(
296                "Cannot convert {:?} to bool", value
297            ))),
298        }
299    }
300}
301
302// =============================================================================
303// FromOptionalTushareValue implementations for basic types
304// =============================================================================
305
306impl FromOptionalTushareValue for String {
307    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
308        if value.is_null() {
309            Ok(None)
310        } else {
311            match value {
312                Value::String(s) if s.is_empty() => Ok(None),
313                _ => String::from_tushare_value(value).map(Some)
314            }
315        }
316    }
317}
318
319impl FromOptionalTushareValue for f64 {
320    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
321        if value.is_null() {
322            Ok(None)
323        } else {
324            f64::from_tushare_value(value).map(Some)
325        }
326    }
327}
328
329impl FromOptionalTushareValue for f32 {
330    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
331        if value.is_null() {
332            Ok(None)
333        } else {
334            f32::from_tushare_value(value).map(Some)
335        }
336    }
337}
338
339impl FromOptionalTushareValue for i64 {
340    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
341        if value.is_null() {
342            Ok(None)
343        } else {
344            i64::from_tushare_value(value).map(Some)
345        }
346    }
347}
348
349impl FromOptionalTushareValue for i32 {
350    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
351        if value.is_null() {
352            Ok(None)
353        } else {
354            i32::from_tushare_value(value).map(Some)
355        }
356    }
357}
358
359impl FromOptionalTushareValue for i16 {
360    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
361        if value.is_null() {
362            Ok(None)
363        } else {
364            i16::from_tushare_value(value).map(Some)
365        }
366    }
367}
368
369impl FromOptionalTushareValue for i8 {
370    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
371        if value.is_null() {
372            Ok(None)
373        } else {
374            i8::from_tushare_value(value).map(Some)
375        }
376    }
377}
378
379impl FromOptionalTushareValue for u64 {
380    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
381        if value.is_null() {
382            Ok(None)
383        } else {
384            u64::from_tushare_value(value).map(Some)
385        }
386    }
387}
388
389impl FromOptionalTushareValue for u32 {
390    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
391        if value.is_null() {
392            Ok(None)
393        } else {
394            u32::from_tushare_value(value).map(Some)
395        }
396    }
397}
398
399impl FromOptionalTushareValue for u16 {
400    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
401        if value.is_null() {
402            Ok(None)
403        } else {
404            u16::from_tushare_value(value).map(Some)
405        }
406    }
407}
408
409impl FromOptionalTushareValue for u8 {
410    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
411        if value.is_null() {
412            Ok(None)
413        } else {
414            u8::from_tushare_value(value).map(Some)
415        }
416    }
417}
418
419impl FromOptionalTushareValue for usize {
420    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
421        if value.is_null() {
422            Ok(None)
423        } else {
424            usize::from_tushare_value(value).map(Some)
425        }
426    }
427}
428
429impl FromOptionalTushareValue for isize {
430    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
431        if value.is_null() {
432            Ok(None)
433        } else {
434            isize::from_tushare_value(value).map(Some)
435        }
436    }
437}
438
439impl FromOptionalTushareValue for bool {
440    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
441        if value.is_null() {
442            Ok(None)
443        } else {
444            bool::from_tushare_value(value).map(Some)
445        }
446    }
447}
448
449// Additional type implementations
450
451impl FromTushareValue for char {
452    fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
453        match value {
454            Value::String(s) => {
455                let mut chars = s.chars();
456                match (chars.next(), chars.next()) {
457                    (Some(c), None) => Ok(c), // Exactly one character
458                    (Some(_), Some(_)) => Err(TushareError::ParseError(format!(
459                        "String '{}' contains more than one character", s
460                    ))),
461                    (None, None) => Err(TushareError::ParseError(
462                        "Cannot convert empty string to char".to_string()
463                    )),
464                    (None, Some(_)) => unreachable!("This case is impossible"),
465                }
466            },
467            Value::Number(n) => {
468                if let Some(i) = n.as_u64() {
469                    if i <= u32::MAX as u64 {
470                        char::from_u32(i as u32).ok_or_else(|| {
471                            TushareError::ParseError(format!("Invalid Unicode code point: {}", i))
472                        })
473                    } else {
474                        Err(TushareError::ParseError(format!(
475                            "Number {} is too large for Unicode code point", i
476                        )))
477                    }
478                } else {
479                    Err(TushareError::ParseError(format!(
480                        "Cannot convert {:?} to char", n
481                    )))
482                }
483            },
484            _ => Err(TushareError::ParseError(format!(
485                "Cannot convert {:?} to char", value
486            ))),
487        }
488    }
489}
490
491impl FromOptionalTushareValue for char {
492    fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
493        if value.is_null() {
494            Ok(None)
495        } else {
496            char::from_tushare_value(value).map(Some)
497        }
498    }
499}
500
501// Note: &str cannot implement FromTushareValue directly because it's a borrowed type
502// and the trait requires returning an owned value. Users should use String instead
503// and convert to &str as needed. However, we can provide a helper comment:
504//
505// For &str usage, convert from String:
506// let s: String = String::from_tushare_value(value)?;
507// let str_ref: &str = &s;