Skip to main content

scratch_test_value/conversions/
from_components.rs

1#[cfg(feature = "serde_json")]
2use crate::SNumber;
3use crate::{ARc, SValue};
4
5impl std::str::FromStr for SValue {
6    type Err = std::convert::Infallible;
7    fn from_str(s: &str) -> Result<Self, Self::Err> {
8        Ok(if let Ok(int) = s.parse() {
9            Self::Int(int)
10        } else if let Ok(float) = s.parse() {
11            if s.contains(".") || float < (i64::MIN as f64) || (i64::MAX as f64) < float {
12                Self::Float(float)
13            } else if let Ok(int) = s.parse() {
14                Self::Int(int)
15            } else {
16                Self::Text(s.into())
17            }
18        } else if s == "true" {
19            Self::Bool(true)
20        } else if s == "false" {
21            Self::Bool(false)
22        } else {
23            Self::Text(s.into())
24        })
25    }
26}
27
28impl From<String> for SValue {
29    fn from(value: String) -> Self {
30        Self::Text(value.into())
31    }
32}
33
34impl<'a> From<&'a str> for SValue {
35    fn from(value: &'a str) -> Self {
36        Self::Text(value.into())
37    }
38}
39
40impl From<ARc<str>> for SValue {
41    fn from(value: ARc<str>) -> Self {
42        Self::Text(value)
43    }
44}
45impl From<i64> for SValue {
46    fn from(value: i64) -> Self {
47        Self::Int(value)
48    }
49}
50impl From<f64> for SValue {
51    fn from(value: f64) -> Self {
52        Self::Float(value)
53    }
54}
55
56#[cfg(feature = "serde_json")]
57impl From<serde_json::Number> for SValue {
58    fn from(value: serde_json::Number) -> SValue {
59        SNumber::from(value).into()
60    }
61}
62#[cfg(feature = "serde_json")]
63impl From<serde_json::Number> for SNumber {
64    fn from(value: serde_json::Number) -> SNumber {
65        if let Some(n) = value.as_f64() {
66            Self::Float(n)
67        } else if let Some(n) = value.as_i64() {
68            Self::Int(n)
69        } else if let Some(n) = value.as_u64() {
70            if let Ok(i) = n.try_into() {
71                Self::Int(i)
72            } else {
73                Self::Float(n as f64)
74            }
75        } else {
76            Self::Int(0)
77        }
78    }
79}
80
81#[cfg(feature = "serde_json")]
82#[derive(Debug, PartialEq, Eq, Clone, thiserror::Error)]
83#[error("json value can't be converted into Scratch value (object/array?): {0}")]
84pub struct JsonValueNoSValue(pub serde_json::Value);
85
86#[cfg(feature = "serde_json")]
87impl TryFrom<serde_json::Value> for SValue {
88    type Error = JsonValueNoSValue;
89
90    fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> {
91        let initial = if let Some(num) = value.as_number() {
92            // TODO: HINT integer out of range case is ignored
93            SValue::from(num.clone())
94        } else if let Some(boo) = value.as_bool() {
95            SValue::Bool(boo)
96        } else if let Some(tex) = value.as_str() {
97            SValue::Text(tex.into())
98        } else {
99            return Err(JsonValueNoSValue(value));
100        };
101        Ok(initial)
102    }
103}