json_gettext/value/
value_impl.rs

1extern crate serde;
2
3#[cfg(feature = "rocket")]
4extern crate rocket;
5
6#[cfg(feature = "rocket")]
7use std::io::Cursor;
8use std::{
9    convert::TryFrom,
10    fmt::{self, Display, Formatter},
11    str::FromStr,
12};
13
14#[cfg(feature = "rocket")]
15use rocket::form::{self, FromFormField, ValueField};
16#[cfg(feature = "rocket")]
17use rocket::request::{FromParam, Request};
18#[cfg(feature = "rocket")]
19use rocket::response::{self, Responder, Response};
20use serde::{
21    de::{Error as DeError, MapAccess, SeqAccess, Visitor},
22    Deserialize, Deserializer, Serialize, Serializer,
23};
24
25use super::JSONGetTextValueError;
26use crate::serde_json::{self, to_value, Map, Value};
27
28/// Represents any valid JSON value. Reference can also be wrapped.
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub enum JSONGetTextValue<'a> {
31    Str(&'a str),
32    JSONValue(Value),
33    JSONValueRef(&'a Value),
34}
35
36impl<'a> JSONGetTextValue<'a> {
37    #[inline]
38    #[allow(clippy::should_implement_trait)]
39    pub fn from_str<S: AsRef<str> + ?Sized>(s: &'a S) -> JSONGetTextValue<'a> {
40        JSONGetTextValue::Str(s.as_ref())
41    }
42
43    #[inline]
44    pub fn from_string<S: Into<String>>(s: S) -> JSONGetTextValue<'static> {
45        JSONGetTextValue::JSONValue(Value::String(s.into()))
46    }
47
48    #[inline]
49    pub fn from_json_str<S: AsRef<str>>(
50        s: S,
51    ) -> Result<JSONGetTextValue<'static>, JSONGetTextValueError> {
52        JSONGetTextValue::parse_json(s)
53    }
54
55    #[inline]
56    pub fn from_bool(b: bool) -> JSONGetTextValue<'static> {
57        JSONGetTextValue::JSONValue(Value::Bool(b))
58    }
59
60    #[inline]
61    pub fn from_i8(n: i8) -> JSONGetTextValue<'static> {
62        JSONGetTextValue::JSONValue(to_value(n).unwrap())
63    }
64
65    #[inline]
66    pub fn from_i16(n: i16) -> JSONGetTextValue<'static> {
67        JSONGetTextValue::JSONValue(to_value(n).unwrap())
68    }
69
70    #[inline]
71    pub fn from_i32(n: i32) -> JSONGetTextValue<'static> {
72        JSONGetTextValue::JSONValue(to_value(n).unwrap())
73    }
74
75    #[inline]
76    pub fn from_i64(n: i64) -> JSONGetTextValue<'static> {
77        JSONGetTextValue::JSONValue(to_value(n).unwrap())
78    }
79
80    #[inline]
81    pub fn from_i128(n: i128) -> Result<JSONGetTextValue<'static>, JSONGetTextValueError> {
82        Ok(JSONGetTextValue::JSONValue(
83            to_value(n).map_err(|_| JSONGetTextValueError::IntegerOutOfRange)?,
84        ))
85    }
86
87    #[inline]
88    pub fn from_isize(n: isize) -> JSONGetTextValue<'static> {
89        JSONGetTextValue::JSONValue(to_value(n).unwrap())
90    }
91
92    #[inline]
93    pub fn from_u8(n: u8) -> JSONGetTextValue<'static> {
94        JSONGetTextValue::JSONValue(to_value(n).unwrap())
95    }
96
97    #[inline]
98    pub fn from_u16(n: u16) -> JSONGetTextValue<'static> {
99        JSONGetTextValue::JSONValue(to_value(n).unwrap())
100    }
101
102    #[inline]
103    pub fn from_u32(n: u32) -> JSONGetTextValue<'static> {
104        JSONGetTextValue::JSONValue(to_value(n).unwrap())
105    }
106
107    #[inline]
108    pub fn from_u64(n: u64) -> JSONGetTextValue<'static> {
109        JSONGetTextValue::JSONValue(to_value(n).unwrap())
110    }
111
112    #[inline]
113    pub fn from_u128(n: u128) -> Result<JSONGetTextValue<'static>, JSONGetTextValueError> {
114        Ok(JSONGetTextValue::JSONValue(
115            to_value(n).map_err(|_| JSONGetTextValueError::IntegerOutOfRange)?,
116        ))
117    }
118
119    #[inline]
120    pub fn from_usize(n: usize) -> JSONGetTextValue<'static> {
121        JSONGetTextValue::JSONValue(to_value(n).unwrap())
122    }
123
124    #[inline]
125    pub fn from_f32(n: f32) -> JSONGetTextValue<'static> {
126        JSONGetTextValue::JSONValue(to_value(n).unwrap())
127    }
128
129    #[inline]
130    pub fn from_f64(n: f64) -> JSONGetTextValue<'static> {
131        JSONGetTextValue::JSONValue(to_value(n).unwrap())
132    }
133
134    #[inline]
135    pub fn from_json_value(v: Value) -> JSONGetTextValue<'static> {
136        JSONGetTextValue::JSONValue(v)
137    }
138
139    #[inline]
140    pub fn from_json_value_ref(v: &'a Value) -> JSONGetTextValue<'a> {
141        JSONGetTextValue::JSONValueRef(v)
142    }
143
144    #[inline]
145    pub fn from_serializable<T: Serialize>(
146        v: T,
147    ) -> Result<JSONGetTextValue<'static>, serde_json::Error> {
148        Ok(JSONGetTextValue::JSONValue(to_value(v)?))
149    }
150
151    #[inline]
152    pub fn null() -> JSONGetTextValue<'static> {
153        JSONGetTextValue::JSONValue(Value::Null)
154    }
155}
156
157impl<'a> JSONGetTextValue<'a> {
158    /// Convert to a string for JSON format.
159    pub fn to_json_string(&self) -> String {
160        match self {
161            JSONGetTextValue::Str(s) => {
162                let mut string = String::with_capacity(s.len() + 2);
163                string.push('"');
164
165                let mut from = 0;
166
167                for (i, c) in s.char_indices() {
168                    let esc = c.escape_debug();
169
170                    if esc.len() != 1 {
171                        string.push_str(&s[from..i]);
172
173                        for c in esc {
174                            string.push(c);
175                        }
176
177                        from = i + c.len_utf8();
178                    }
179                }
180
181                string.push_str(&s[from..]);
182                string.push('"');
183
184                string
185            },
186            JSONGetTextValue::JSONValue(v) => v.to_string(),
187            JSONGetTextValue::JSONValueRef(v) => v.to_string(),
188        }
189    }
190
191    #[deprecated(since = "3.2.0", note = "Please use the `to_json_string` function instead")]
192    /// Convert to a string for JSON format.
193    #[inline]
194    pub fn to_json(&self) -> String {
195        self.to_json_string()
196    }
197
198    /// Convert to a string slice if it is possible (if it is a string).
199    #[inline]
200    pub fn as_str(&self) -> Option<&str> {
201        match self {
202            JSONGetTextValue::Str(s) => Some(s),
203            JSONGetTextValue::JSONValue(v) => match v {
204                Value::String(s) => Some(s),
205                _ => None,
206            },
207            JSONGetTextValue::JSONValueRef(v) => match v {
208                Value::String(s) => Some(s),
209                _ => None,
210            },
211        }
212    }
213
214    /// Clone the reference of this `JSONGetTextValue` instance.
215    #[inline]
216    pub fn clone_borrowed(&self) -> JSONGetTextValue {
217        match self {
218            JSONGetTextValue::Str(s) => JSONGetTextValue::Str(s),
219            JSONGetTextValue::JSONValue(v) => JSONGetTextValue::JSONValueRef(v),
220            JSONGetTextValue::JSONValueRef(v) => JSONGetTextValue::JSONValueRef(v),
221        }
222    }
223}
224
225impl<'a> PartialEq<JSONGetTextValue<'a>> for str {
226    #[inline]
227    fn eq(&self, other: &JSONGetTextValue) -> bool {
228        match other {
229            JSONGetTextValue::Str(s) => s.eq(&self),
230            JSONGetTextValue::JSONValue(v) => v.eq(&self),
231            JSONGetTextValue::JSONValueRef(v) => v.eq(&self),
232        }
233    }
234}
235
236impl<'a> PartialEq<JSONGetTextValue<'a>> for &'a str {
237    #[inline]
238    fn eq(&self, other: &JSONGetTextValue) -> bool {
239        match other {
240            JSONGetTextValue::Str(s) => s.eq(self),
241            JSONGetTextValue::JSONValue(v) => v.eq(self),
242            JSONGetTextValue::JSONValueRef(v) => v.eq(self),
243        }
244    }
245}
246
247impl<'a> PartialEq<str> for JSONGetTextValue<'a> {
248    #[inline]
249    fn eq(&self, other: &str) -> bool {
250        match self {
251            JSONGetTextValue::Str(s) => s.eq(&other),
252            JSONGetTextValue::JSONValue(v) => v.eq(&other),
253            JSONGetTextValue::JSONValueRef(v) => v.eq(&other),
254        }
255    }
256}
257
258impl<'a> Display for JSONGetTextValue<'a> {
259    #[inline]
260    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
261        match self {
262            JSONGetTextValue::Str(s) => s.fmt(f),
263            JSONGetTextValue::JSONValue(v) => match v.as_str() {
264                Some(s) => s.fmt(f),
265                None => v.fmt(f),
266            },
267            JSONGetTextValue::JSONValueRef(v) => match v.as_str() {
268                Some(s) => s.fmt(f),
269                None => v.fmt(f),
270            },
271        }
272    }
273}
274
275impl<'a> From<&'a str> for JSONGetTextValue<'a> {
276    #[inline]
277    fn from(v: &'a str) -> JSONGetTextValue<'a> {
278        JSONGetTextValue::from_str(v)
279    }
280}
281
282impl From<String> for JSONGetTextValue<'static> {
283    #[inline]
284    fn from(v: String) -> JSONGetTextValue<'static> {
285        JSONGetTextValue::from_string(v)
286    }
287}
288
289impl From<bool> for JSONGetTextValue<'static> {
290    #[inline]
291    fn from(v: bool) -> JSONGetTextValue<'static> {
292        JSONGetTextValue::from_bool(v)
293    }
294}
295
296impl From<i8> for JSONGetTextValue<'static> {
297    #[inline]
298    fn from(v: i8) -> JSONGetTextValue<'static> {
299        JSONGetTextValue::from_i8(v)
300    }
301}
302
303impl From<i16> for JSONGetTextValue<'static> {
304    #[inline]
305    fn from(v: i16) -> JSONGetTextValue<'static> {
306        JSONGetTextValue::from_i16(v)
307    }
308}
309
310impl From<i32> for JSONGetTextValue<'static> {
311    #[inline]
312    fn from(v: i32) -> JSONGetTextValue<'static> {
313        JSONGetTextValue::from_i32(v)
314    }
315}
316
317impl From<i64> for JSONGetTextValue<'static> {
318    #[inline]
319    fn from(v: i64) -> JSONGetTextValue<'static> {
320        JSONGetTextValue::from_i64(v)
321    }
322}
323
324impl From<isize> for JSONGetTextValue<'static> {
325    #[inline]
326    fn from(v: isize) -> JSONGetTextValue<'static> {
327        JSONGetTextValue::from_isize(v)
328    }
329}
330
331impl TryFrom<i128> for JSONGetTextValue<'static> {
332    type Error = JSONGetTextValueError;
333
334    #[inline]
335    fn try_from(v: i128) -> Result<JSONGetTextValue<'static>, JSONGetTextValueError> {
336        JSONGetTextValue::from_i128(v)
337    }
338}
339
340impl From<u8> for JSONGetTextValue<'static> {
341    #[inline]
342    fn from(v: u8) -> JSONGetTextValue<'static> {
343        JSONGetTextValue::from_u8(v)
344    }
345}
346
347impl From<u16> for JSONGetTextValue<'static> {
348    #[inline]
349    fn from(v: u16) -> JSONGetTextValue<'static> {
350        JSONGetTextValue::from_u16(v)
351    }
352}
353
354impl From<u32> for JSONGetTextValue<'static> {
355    #[inline]
356    fn from(v: u32) -> JSONGetTextValue<'static> {
357        JSONGetTextValue::from_u32(v)
358    }
359}
360
361impl From<u64> for JSONGetTextValue<'static> {
362    #[inline]
363    fn from(v: u64) -> JSONGetTextValue<'static> {
364        JSONGetTextValue::from_u64(v)
365    }
366}
367
368impl From<usize> for JSONGetTextValue<'static> {
369    #[inline]
370    fn from(v: usize) -> JSONGetTextValue<'static> {
371        JSONGetTextValue::from_usize(v)
372    }
373}
374
375impl TryFrom<u128> for JSONGetTextValue<'static> {
376    type Error = JSONGetTextValueError;
377
378    #[inline]
379    fn try_from(v: u128) -> Result<JSONGetTextValue<'static>, JSONGetTextValueError> {
380        JSONGetTextValue::from_u128(v)
381    }
382}
383
384impl From<f32> for JSONGetTextValue<'static> {
385    #[inline]
386    fn from(v: f32) -> JSONGetTextValue<'static> {
387        JSONGetTextValue::from_f32(v)
388    }
389}
390
391impl From<f64> for JSONGetTextValue<'static> {
392    #[inline]
393    fn from(v: f64) -> JSONGetTextValue<'static> {
394        JSONGetTextValue::from_f64(v)
395    }
396}
397
398impl From<Value> for JSONGetTextValue<'static> {
399    #[inline]
400    fn from(v: Value) -> JSONGetTextValue<'static> {
401        JSONGetTextValue::from_json_value(v)
402    }
403}
404
405impl<'a> From<&'a Value> for JSONGetTextValue<'a> {
406    #[inline]
407    fn from(v: &'a Value) -> JSONGetTextValue<'a> {
408        JSONGetTextValue::from_json_value_ref(v)
409    }
410}
411
412impl FromStr for JSONGetTextValue<'static> {
413    type Err = ();
414
415    #[inline]
416    fn from_str(s: &str) -> Result<Self, Self::Err> {
417        Ok(JSONGetTextValue::from_string(s))
418    }
419}
420
421// TODO serde
422
423impl<'a> JSONGetTextValue<'a> {
424    #[inline]
425    pub fn parse_json<S: AsRef<str>>(
426        s: S,
427    ) -> Result<JSONGetTextValue<'static>, JSONGetTextValueError> {
428        Ok(JSONGetTextValue::JSONValue(serde_json::from_str(s.as_ref())?))
429    }
430}
431
432impl<'a> Serialize for JSONGetTextValue<'a> {
433    #[inline]
434    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
435    where
436        S: Serializer, {
437        match self {
438            JSONGetTextValue::Str(s) => s.serialize(serializer),
439            JSONGetTextValue::JSONValue(v) => v.serialize(serializer),
440            JSONGetTextValue::JSONValueRef(v) => v.serialize(serializer),
441        }
442    }
443}
444
445struct JSONGetTextValueVisitor;
446
447impl<'de> Visitor<'de> for JSONGetTextValueVisitor {
448    type Value = JSONGetTextValue<'de>;
449
450    serde::serde_if_integer128! {
451        #[inline]
452        fn visit_i128<E>(self, v: i128) -> Result<JSONGetTextValue<'static>, E> where E: DeError {
453            JSONGetTextValue::from_i128(v).map_err(DeError::custom)
454        }
455    }
456
457    serde::serde_if_integer128! {
458        #[inline]
459        fn visit_u128<E>(self, v: u128) -> Result<JSONGetTextValue<'static>, E> where E: DeError {
460            JSONGetTextValue::from_u128(v).map_err(DeError::custom)
461        }
462    }
463
464    #[inline]
465    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
466        formatter.write_str("a json value")
467    }
468
469    #[inline]
470    fn visit_bool<E>(self, v: bool) -> Result<JSONGetTextValue<'static>, E>
471    where
472        E: DeError, {
473        Ok(JSONGetTextValue::from_bool(v))
474    }
475
476    #[inline]
477    fn visit_i64<E>(self, v: i64) -> Result<JSONGetTextValue<'static>, E>
478    where
479        E: DeError, {
480        Ok(JSONGetTextValue::from_i64(v))
481    }
482
483    #[inline]
484    fn visit_u64<E>(self, v: u64) -> Result<JSONGetTextValue<'static>, E>
485    where
486        E: DeError, {
487        Ok(JSONGetTextValue::from_u64(v))
488    }
489
490    #[inline]
491    fn visit_f64<E>(self, v: f64) -> Result<JSONGetTextValue<'static>, E>
492    where
493        E: DeError, {
494        Ok(JSONGetTextValue::from_f64(v))
495    }
496
497    #[inline]
498    fn visit_str<E>(self, v: &str) -> Result<JSONGetTextValue<'static>, E>
499    where
500        E: DeError, {
501        Ok(JSONGetTextValue::from_string(v.to_string()))
502    }
503
504    #[inline]
505    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<JSONGetTextValue<'de>, E>
506    where
507        E: DeError, {
508        Ok(JSONGetTextValue::from_str(v))
509    }
510
511    #[inline]
512    fn visit_string<E>(self, v: String) -> Result<JSONGetTextValue<'static>, E>
513    where
514        E: DeError, {
515        Ok(JSONGetTextValue::from_string(v))
516    }
517
518    #[inline]
519    fn visit_none<E>(self) -> Result<JSONGetTextValue<'static>, E>
520    where
521        E: DeError, {
522        Ok(JSONGetTextValue::null())
523    }
524
525    #[inline]
526    fn visit_seq<A>(self, mut seq: A) -> Result<JSONGetTextValue<'static>, A::Error>
527    where
528        A: SeqAccess<'de>, {
529        let mut v = match seq.size_hint() {
530            Some(size) => Vec::with_capacity(size),
531            None => Vec::new(),
532        };
533
534        while let Some(e) = seq.next_element()? {
535            v.push(e);
536        }
537
538        Ok(JSONGetTextValue::from_json_value(Value::Array(v)))
539    }
540
541    #[inline]
542    fn visit_map<A>(self, mut map: A) -> Result<JSONGetTextValue<'static>, A::Error>
543    where
544        A: MapAccess<'de>, {
545        let mut v = match map.size_hint() {
546            Some(size) => Map::with_capacity(size),
547            None => Map::new(),
548        };
549
550        while let Some((k, e)) = map.next_entry()? {
551            v.insert(k, e);
552        }
553
554        Ok(JSONGetTextValue::from_json_value(Value::Object(v)))
555    }
556}
557
558impl<'de> Deserialize<'de> for JSONGetTextValue<'de> {
559    #[inline]
560    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
561    where
562        D: Deserializer<'de>, {
563        deserializer.deserialize_str(JSONGetTextValueVisitor)
564    }
565}
566
567// TODO Rocket
568
569#[cfg(feature = "rocket")]
570impl<'r, 'o: 'r> Responder<'r, 'o> for JSONGetTextValue<'o> {
571    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {
572        let mut response = Response::build();
573
574        let s = self.to_json_string();
575
576        response
577            .raw_header("Content-Type", "application/json")
578            .raw_header("Content-Length", format!("{}", s.len()))
579            .sized_body(s.len(), Cursor::new(s));
580
581        response.ok()
582    }
583}
584
585#[cfg(feature = "rocket")]
586impl<'a> FromParam<'a> for JSONGetTextValue<'a> {
587    type Error = JSONGetTextValueError;
588
589    fn from_param(param: &'a str) -> Result<Self, Self::Error> {
590        JSONGetTextValue::parse_json(param)
591    }
592}
593
594#[cfg(feature = "rocket")]
595#[rocket::async_trait]
596impl<'v> FromFormField<'v> for JSONGetTextValue<'v> {
597    fn from_value(field: ValueField<'v>) -> form::Result<'v, Self> {
598        Ok(JSONGetTextValue::parse_json(field.value).map_err(form::Error::custom)?)
599    }
600}