firebase_rs_sdk/remote_config/
value.rs1#[derive(Clone, Debug, PartialEq, Eq)]
8pub enum RemoteConfigValueSource {
9 Remote,
11 Default,
13 Static,
15}
16
17impl RemoteConfigValueSource {
18 pub fn as_str(&self) -> &'static str {
20 match self {
21 RemoteConfigValueSource::Remote => "remote",
22 RemoteConfigValueSource::Default => "default",
23 RemoteConfigValueSource::Static => "static",
24 }
25 }
26}
27
28#[derive(Clone, Debug, PartialEq, Eq)]
33pub struct RemoteConfigValue {
34 source: RemoteConfigValueSource,
35 value: String,
36}
37
38impl RemoteConfigValue {
39 const DEFAULT_BOOLEAN: bool = false;
40 const DEFAULT_NUMBER: f64 = 0.0;
41 const BOOLEAN_TRUTHY_VALUES: [&'static str; 6] = ["1", "true", "t", "yes", "y", "on"];
42
43 pub(crate) fn new(source: RemoteConfigValueSource, value: impl Into<String>) -> Self {
44 Self {
45 source,
46 value: value.into(),
47 }
48 }
49
50 pub(crate) fn static_value() -> Self {
51 Self::new(RemoteConfigValueSource::Static, String::new())
52 }
53
54 pub fn as_string(&self) -> String {
65 self.value.clone()
66 }
67
68 pub fn as_bool(&self) -> bool {
73 if self.source == RemoteConfigValueSource::Static {
74 return Self::DEFAULT_BOOLEAN;
75 }
76 Self::BOOLEAN_TRUTHY_VALUES
77 .iter()
78 .any(|truthy| self.value.eq_ignore_ascii_case(truthy))
79 }
80
81 pub fn as_number(&self) -> f64 {
85 if self.source == RemoteConfigValueSource::Static {
86 return Self::DEFAULT_NUMBER;
87 }
88 match self.value.trim().parse::<f64>() {
89 Ok(parsed) if parsed.is_finite() || parsed == 0.0 => parsed,
90 Ok(parsed) if parsed.is_nan() => Self::DEFAULT_NUMBER,
91 Ok(parsed) => parsed,
92 Err(_) => Self::DEFAULT_NUMBER,
93 }
94 }
95
96 pub fn source(&self) -> RemoteConfigValueSource {
98 self.source.clone()
99 }
100}
101
102impl Default for RemoteConfigValue {
103 fn default() -> Self {
104 Self::static_value()
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn boolean_truthy_values_match_js_behaviour() {
114 for truthy in RemoteConfigValue::BOOLEAN_TRUTHY_VALUES {
115 let value = RemoteConfigValue::new(RemoteConfigValueSource::Remote, truthy);
116 assert!(
117 value.as_bool(),
118 "expected truthy value {} to be true",
119 truthy
120 );
121 }
122 let value = RemoteConfigValue::new(RemoteConfigValueSource::Remote, "false");
123 assert!(!value.as_bool());
124 }
125
126 #[test]
127 fn static_boolean_is_false() {
128 let value = RemoteConfigValue::static_value();
129 assert!(!value.as_bool());
130 }
131
132 #[test]
133 fn number_parsing_matches_js_defaults() {
134 let value = RemoteConfigValue::new(RemoteConfigValueSource::Default, "42.5");
135 assert_eq!(value.as_number(), 42.5);
136
137 let invalid = RemoteConfigValue::new(RemoteConfigValueSource::Remote, "NaN");
138 assert_eq!(invalid.as_number(), 0.0);
139
140 let static_value = RemoteConfigValue::static_value();
141 assert_eq!(static_value.as_number(), 0.0);
142 }
143}