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#[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 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 #[inline]
194 pub fn to_json(&self) -> String {
195 self.to_json_string()
196 }
197
198 #[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 #[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
421impl<'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#[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}