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