1use std::{borrow::Cow, fmt};
32
33use serde::{
34 de::{self, Deserializer, Unexpected, Visitor},
35 ser::Serializer,
36 Deserialize, Serialize,
37};
38use serde_json::Value as JsonValue;
39
40use crate::{
41 error::{ErrorCode, INVALID_PARAMS_MSG},
42 ErrorObject, ErrorObjectOwned,
43};
44
45#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
47pub struct TwoPointZero;
48
49struct TwoPointZeroVisitor;
50
51impl Visitor<'_> for TwoPointZeroVisitor {
52 type Value = TwoPointZero;
53
54 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
55 formatter.write_str(r#"a string "2.0""#)
56 }
57
58 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
59 where
60 E: de::Error,
61 {
62 match s {
63 "2.0" => Ok(TwoPointZero),
64 _ => Err(de::Error::invalid_value(Unexpected::Str(s), &self)),
65 }
66 }
67}
68
69impl<'de> Deserialize<'de> for TwoPointZero {
70 fn deserialize<D>(deserializer: D) -> Result<TwoPointZero, D::Error>
71 where
72 D: Deserializer<'de>,
73 {
74 deserializer.deserialize_str(TwoPointZeroVisitor)
75 }
76}
77
78impl Serialize for TwoPointZero {
79 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
80 where
81 S: Serializer,
82 {
83 serializer.serialize_str("2.0")
84 }
85}
86
87#[derive(Clone, Debug)]
93pub struct Params<'a>(Option<Cow<'a, str>>);
94
95impl<'a> Params<'a> {
96 pub fn new(raw: Option<&'a str>) -> Self {
98 Self(raw.map(|r| r.trim().into()))
99 }
100
101 pub fn sequence(&self) -> ParamsSequence<'_> {
107 let json = match self.0.as_ref() {
108 Some(json) if json == "[]" => "",
110 Some(json) => json,
111 None => "",
112 };
113 ParamsSequence(json)
114 }
115
116 pub fn parse<T>(&'a self) -> Result<T, ErrorObjectOwned>
118 where
119 T: Deserialize<'a>,
120 {
121 let params = self.0.as_ref().map(AsRef::as_ref).unwrap_or("null");
123 serde_json::from_str(params).map_err(invalid_params)
124 }
125
126 pub fn one<T>(&'a self) -> Result<T, ErrorObjectOwned>
129 where
130 T: Deserialize<'a>,
131 {
132 self.parse::<[T; 1]>().map(|[res]| res)
133 }
134
135 pub fn into_owned(self) -> Params<'static> {
139 Params(self.0.map(|s| Cow::Owned(s.into_owned())))
140 }
141
142 pub fn len_bytes(&self) -> usize {
144 match self.0 {
145 Some(ref cow) => cow.len(),
146 None => 0,
147 }
148 }
149
150 pub fn as_str(&self) -> Option<&str> {
152 match self.0 {
153 Some(ref cow) => Some(cow.as_ref()),
154 None => None,
155 }
156 }
157}
158
159#[derive(Debug, Copy, Clone)]
168pub struct ParamsSequence<'a>(&'a str);
169
170impl<'a> ParamsSequence<'a> {
171 fn next_inner<T>(&mut self) -> Option<Result<T, ErrorObjectOwned>>
172 where
173 T: Deserialize<'a>,
174 {
175 let mut json = self.0;
176 match json.as_bytes().first()? {
177 b']' => {
178 self.0 = "";
179 return None;
180 }
181 b'[' | b',' => json = &json[1..],
182 _ => {
183 let errmsg =
184 format!("Invalid params. Expected one of '[', ']' or ',' but found {json:?}");
185 return Some(Err(invalid_params(errmsg)));
186 }
187 }
188
189 let mut iter = serde_json::Deserializer::from_str(json).into_iter::<T>();
190
191 match iter.next()? {
192 Ok(value) => {
193 self.0 = json[iter.byte_offset()..].trim_start();
194
195 Some(Ok(value))
196 }
197 Err(e) => {
198 self.0 = "";
199 Some(Err(invalid_params(e)))
200 }
201 }
202 }
203
204 #[allow(clippy::should_implement_trait)]
220 pub fn next<T>(&mut self) -> Result<T, ErrorObjectOwned>
221 where
222 T: Deserialize<'a>,
223 {
224 match self.next_inner() {
225 Some(result) => result,
226 None => Err(invalid_params("No more params")),
227 }
228 }
229
230 pub fn optional_next<T>(&mut self) -> Result<Option<T>, ErrorObjectOwned>
249 where
250 T: Deserialize<'a>,
251 {
252 match self.next_inner::<Option<T>>() {
253 Some(result) => result,
254 None => Ok(None),
255 }
256 }
257}
258
259#[derive(Debug, PartialEq, Clone, Hash, Eq, Serialize)]
261#[serde(untagged)]
262pub enum SubscriptionId<'a> {
263 Num(u64),
265 Str(Cow<'a, str>),
267}
268
269impl From<SubscriptionId<'_>> for JsonValue {
270 fn from(sub_id: SubscriptionId) -> Self {
271 match sub_id {
272 SubscriptionId::Num(n) => n.into(),
273 SubscriptionId::Str(s) => s.into_owned().into(),
274 }
275 }
276}
277
278impl From<u64> for SubscriptionId<'_> {
279 fn from(sub_id: u64) -> Self {
280 Self::Num(sub_id)
281 }
282}
283
284impl From<String> for SubscriptionId<'_> {
285 fn from(sub_id: String) -> Self {
286 Self::Str(sub_id.into())
287 }
288}
289
290impl<'a> TryFrom<JsonValue> for SubscriptionId<'a> {
291 type Error = ();
292
293 fn try_from(json: JsonValue) -> Result<SubscriptionId<'a>, ()> {
294 match json {
295 JsonValue::String(s) => Ok(SubscriptionId::Str(s.into())),
296 JsonValue::Number(n) => {
297 if let Some(n) = n.as_u64() {
298 Ok(SubscriptionId::Num(n))
299 } else {
300 Err(())
301 }
302 }
303 _ => Err(()),
304 }
305 }
306}
307
308impl SubscriptionId<'_> {
309 pub fn into_owned(self) -> SubscriptionId<'static> {
314 match self {
315 SubscriptionId::Num(num) => SubscriptionId::Num(num),
316 SubscriptionId::Str(s) => SubscriptionId::Str(Cow::Owned(s.into_owned())),
317 }
318 }
319}
320
321struct SubscriptionIdVisitor;
322
323impl<'de> Visitor<'de> for SubscriptionIdVisitor {
324 type Value = SubscriptionId<'de>;
325
326 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
327 formatter.write_str("an unsigned integer or a string")
328 }
329
330 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> {
331 Ok(SubscriptionId::Num(v))
332 }
333
334 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
335 where
336 E: de::Error,
337 {
338 u64::try_from(v)
339 .map(SubscriptionId::Num)
340 .map_err(|_| de::Error::invalid_value(Unexpected::Signed(v), &self))
341 }
342
343 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> {
344 Ok(SubscriptionId::Str(Cow::Owned(v.to_owned())))
345 }
346
347 fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E> {
348 Ok(SubscriptionId::Str(Cow::Borrowed(v)))
349 }
350
351 fn visit_string<E>(self, v: String) -> Result<Self::Value, E> {
352 Ok(SubscriptionId::Str(Cow::Owned(v)))
353 }
354}
355
356impl<'de: 'a, 'a> Deserialize<'de> for SubscriptionId<'a> {
359 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
360 where
361 D: Deserializer<'de>,
362 {
363 deserializer.deserialize_any(SubscriptionIdVisitor)
364 }
365}
366
367#[derive(Debug, PartialEq, Clone, Hash, Eq, Serialize, PartialOrd, Ord)]
369#[serde(untagged)]
370pub enum Id<'a> {
371 Null,
373 Number(u64),
375 Str(Cow<'a, str>),
377}
378
379impl Id<'_> {
380 pub fn as_number(&self) -> Option<&u64> {
382 match self {
383 Self::Number(n) => Some(n),
384 _ => None,
385 }
386 }
387
388 pub fn as_str(&self) -> Option<&str> {
390 match self {
391 Self::Str(s) => Some(s.as_ref()),
392 _ => None,
393 }
394 }
395
396 pub fn into_owned(self) -> Id<'static> {
400 match self {
401 Id::Null => Id::Null,
402 Id::Number(num) => Id::Number(num),
403 Id::Str(s) => Id::Str(Cow::Owned(s.into_owned())),
404 }
405 }
406}
407
408impl std::fmt::Display for Id<'_> {
409 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
410 match self {
411 Id::Null => f.write_str("null"),
412 Id::Number(n) => f.write_str(&n.to_string()),
413 Id::Str(s) => f.write_str(s),
414 }
415 }
416}
417
418struct IdVisitor;
419
420impl<'de> Visitor<'de> for IdVisitor {
421 type Value = Id<'de>;
422
423 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
424 formatter.write_str("null, an unsigned integer or a string")
425 }
426
427 fn visit_unit<E>(self) -> Result<Self::Value, E> {
428 Ok(Id::Null)
429 }
430
431 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> {
432 Ok(Id::Number(v))
433 }
434
435 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
436 where
437 E: de::Error,
438 {
439 u64::try_from(v)
440 .map(Id::Number)
441 .map_err(|_| de::Error::invalid_value(Unexpected::Signed(v), &self))
442 }
443
444 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> {
445 Ok(Id::Str(Cow::Owned(v.to_owned())))
446 }
447
448 fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E> {
449 Ok(Id::Str(Cow::Borrowed(v)))
450 }
451
452 fn visit_string<E>(self, v: String) -> Result<Self::Value, E> {
453 Ok(Id::Str(Cow::Owned(v)))
454 }
455}
456
457impl<'de: 'a, 'a> Deserialize<'de> for Id<'a> {
460 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
461 where
462 D: Deserializer<'de>,
463 {
464 deserializer.deserialize_any(IdVisitor)
465 }
466}
467
468fn invalid_params(e: impl ToString) -> ErrorObjectOwned {
469 ErrorObject::owned(ErrorCode::InvalidParams.code(), INVALID_PARAMS_MSG, Some(e.to_string()))
470}
471
472#[cfg(test)]
473mod test {
474 use super::{Cow, Id, JsonValue, Params, SubscriptionId, TwoPointZero};
475 use crate::response::SubscriptionPayload;
476 use serde::Deserialize;
477
478 #[test]
479 fn id_deserialization() {
480 let s = r#""2""#;
481 let deserialized: Id = serde_json::from_str(s).unwrap();
482 match deserialized {
483 Id::Str(ref cow) => {
484 assert!(matches!(cow, Cow::Borrowed(_)));
485 assert_eq!(cow, "2");
486 }
487 _ => panic!("Expected Id::Str"),
488 }
489
490 let s = r#"2"#;
491 let deserialized: Id = serde_json::from_str(s).unwrap();
492 assert_eq!(deserialized, Id::Number(2));
493
494 let s = r#""2x""#;
495 let deserialized: Id = serde_json::from_str(s).unwrap();
496 assert_eq!(deserialized, Id::Str(Cow::Borrowed("2x")));
497
498 let s = r#"[1337]"#;
499 assert!(serde_json::from_str::<Id>(s).is_err());
500
501 let s = r#"[null, 0, 2, "\"3"]"#;
502 let deserialized: Vec<Id> = serde_json::from_str(s).unwrap();
503 assert_eq!(
504 deserialized,
505 vec![Id::Null, Id::Number(0), Id::Number(2), Id::Str("\"3".into())]
506 );
507 }
508
509 #[test]
510 fn id_deserialization_accepts_scalars() {
511 let test_vector = [
512 ("null", Id::Null),
513 ("0", Id::Number(0)),
514 ("18446744073709551615", Id::Number(u64::MAX)),
515 (r#""""#, Id::Str("".into())),
516 (r#""abc""#, Id::Str("abc".into())),
517 ];
518
519 for (ser, expected) in test_vector {
520 let id: Id = serde_json::from_str(ser).unwrap();
521 assert_eq!(id, expected);
522 assert_eq!(serde_json::to_string(&id).unwrap(), ser);
523 }
524 }
525
526 #[test]
527 fn id_deserialization_borrows_only_when_possible() {
528 let id: Id = serde_json::from_str(r#""abc""#).unwrap();
529 assert!(matches!(id, Id::Str(Cow::Borrowed("abc"))));
530
531 let id: Id = serde_json::from_str(r#""a\nc""#).unwrap();
533 assert!(matches!(id, Id::Str(Cow::Owned(_))));
534 assert_eq!(id, Id::Str("a\nc".into()));
535
536 let id = Id::deserialize(JsonValue::from("abc")).unwrap();
537 assert!(matches!(id, Id::Str(Cow::Owned(_))));
538 }
539
540 #[test]
541 fn id_deserialization_rejects_non_scalars() {
542 let test_vector = [
543 ("-1", "invalid value: integer `-1`, expected null, an unsigned integer or a string at line 1 column 2"),
544 ("1.5", "invalid type: floating point `1.5`, expected null, an unsigned integer or a string at line 1 column 3"),
545 ("true", "invalid type: boolean `true`, expected null, an unsigned integer or a string at line 1 column 4"),
546 ("[1]", "invalid type: sequence, expected null, an unsigned integer or a string at line 1 column 1"),
547 (r#"{"a":1}"#, "invalid type: map, expected null, an unsigned integer or a string at line 1 column 1"),
548 ];
549
550 for (ser, expected) in test_vector {
551 let err = serde_json::from_str::<Id>(ser).unwrap_err();
552 assert_eq!(err.to_string(), expected);
553 }
554 }
555
556 #[test]
557 fn id_serialization() {
558 let d = vec![
559 Id::Null,
560 Id::Number(0),
561 Id::Number(2),
562 Id::Number(3),
563 Id::Str("\"3".into()),
564 Id::Str("test".into()),
565 ];
566 let serialized = serde_json::to_string(&d).unwrap();
567 assert_eq!(serialized, r#"[null,0,2,3,"\"3","test"]"#);
568 }
569
570 #[test]
571 fn params_parse() {
572 let none = Params::new(None);
573 assert!(none.sequence().next::<u64>().is_err());
574 assert!(none.parse::<Option<u64>>().is_ok());
575 assert_eq!(none.len_bytes(), 0);
576
577 let array_params = Params::new(Some("[1, 2, 3]"));
578 assert_eq!(array_params.len_bytes(), 9);
579 let arr: Result<[u64; 3], _> = array_params.parse();
580 assert!(arr.is_ok());
581
582 let mut seq = array_params.sequence();
583
584 assert_eq!(seq.next::<u64>().unwrap(), 1);
585 assert_eq!(seq.next::<u64>().unwrap(), 2);
586 assert_eq!(seq.next::<u64>().unwrap(), 3);
587 assert!(seq.next::<u64>().is_err());
588
589 let array_one = Params::new(Some("[1]"));
590 assert_eq!(array_one.len_bytes(), 3);
591 let one: Result<u64, _> = array_one.one();
592 assert!(one.is_ok());
593
594 let object_params = Params::new(Some(r#"{"beef":99,"dinner":0}"#));
595 assert_eq!(object_params.len_bytes(), 22);
596 let obj: Result<JsonValue, _> = object_params.parse();
597 assert!(obj.is_ok());
598 }
599
600 #[test]
601 fn params_parse_empty_json() {
602 let array_params = Params::new(Some("[]"));
603 let arr: Result<Vec<u64>, _> = array_params.parse();
604 assert!(arr.is_ok());
605
606 let obj_params = Params::new(Some("{}"));
607 let obj: Result<JsonValue, _> = obj_params.parse();
608 assert!(obj.is_ok());
609 }
610
611 #[test]
612 fn params_sequence_borrows() {
613 let params = Params::new(Some(r#"["foo", "bar"]"#));
614 let mut seq = params.sequence();
615
616 assert_eq!(seq.next::<&str>().unwrap(), "foo");
617 assert_eq!(seq.next::<&str>().unwrap(), "bar");
618 assert!(seq.next::<&str>().is_err());
619
620 let params: (&str, &str) = params.parse().unwrap();
622 assert_eq!(params, ("foo", "bar"));
623 }
624
625 #[test]
626 fn two_point_zero_serde_works() {
627 let initial_ser = r#""2.0""#;
628 let two_point_zero: TwoPointZero = serde_json::from_str(initial_ser).unwrap();
630 let serialized = serde_json::to_string(&two_point_zero).unwrap();
631 assert_eq!(serialized, initial_ser);
632 }
633
634 #[test]
635 fn subscription_id_serde_works() {
636 let test_vector =
637 &[("42", SubscriptionId::Num(42)), (r#""one""#, SubscriptionId::Str("one".into()))];
638
639 for (initial_ser, expected) in test_vector {
640 let id: SubscriptionId = serde_json::from_str(initial_ser).unwrap();
641 assert_eq!(&id, expected);
642 let serialized = serde_json::to_string(&id).unwrap();
643 assert_eq!(&serialized, initial_ser);
644 }
645 }
646
647 #[test]
648 fn subscription_id_deserialization_borrows_only_when_possible() {
649 let id: SubscriptionId = serde_json::from_str(r#""abc""#).unwrap();
650 assert!(matches!(id, SubscriptionId::Str(Cow::Borrowed("abc"))));
651
652 let id: SubscriptionId = serde_json::from_str(r#""a\nc""#).unwrap();
654 assert!(matches!(id, SubscriptionId::Str(Cow::Owned(_))));
655 assert_eq!(id, SubscriptionId::Str("a\nc".into()));
656
657 let id = SubscriptionId::deserialize(JsonValue::from("abc")).unwrap();
658 assert!(matches!(id, SubscriptionId::Str(Cow::Owned(_))));
659
660 let id: SubscriptionId = serde_json::from_str("18446744073709551615").unwrap();
661 assert_eq!(id, SubscriptionId::Num(u64::MAX));
662 }
663
664 #[test]
665 fn subscription_id_deserialization_rejects_non_scalars() {
666 let test_vector = [
667 ("null", "invalid type: null, expected an unsigned integer or a string at line 1 column 4"),
668 ("-1", "invalid value: integer `-1`, expected an unsigned integer or a string at line 1 column 2"),
669 ("1.5", "invalid type: floating point `1.5`, expected an unsigned integer or a string at line 1 column 3"),
670 ("true", "invalid type: boolean `true`, expected an unsigned integer or a string at line 1 column 4"),
671 ("[1]", "invalid type: sequence, expected an unsigned integer or a string at line 1 column 1"),
672 (r#"{"a":1}"#, "invalid type: map, expected an unsigned integer or a string at line 1 column 1"),
673 ];
674
675 for (ser, expected) in test_vector {
676 let err = serde_json::from_str::<SubscriptionId>(ser).unwrap_err();
677 assert_eq!(err.to_string(), expected);
678 }
679
680 let params = Params::new(Some("[[0,0,0]]"));
682 assert!(params.one::<SubscriptionId>().is_err());
683 }
684
685 #[test]
686 fn subscription_params_serialize_work() {
687 let ser = serde_json::to_string(&SubscriptionPayload {
688 subscription: SubscriptionId::Num(12),
689 result: "goal",
690 })
691 .unwrap();
692 let exp = r#"{"subscription":12,"result":"goal"}"#;
693 assert_eq!(ser, exp);
694 }
695
696 #[test]
697 fn subscription_params_deserialize_work() {
698 let ser = r#"{"subscription":"9","result":"offside"}"#;
699 assert!(
700 serde_json::from_str::<SubscriptionPayload<()>>(ser).is_err(),
701 "invalid type should not be deserializable"
702 );
703 let dsr: SubscriptionPayload<JsonValue> = serde_json::from_str(ser).unwrap();
704 assert_eq!(dsr.subscription, SubscriptionId::Str("9".into()));
705 assert_eq!(dsr.result, serde_json::json!("offside"));
706 }
707
708 #[test]
709 fn params_sequence_optional_ignore_empty() {
710 let params = Params::new(Some(r#"["foo", "bar"]"#));
711 let mut seq = params.sequence();
712
713 assert_eq!(seq.optional_next::<&str>().unwrap(), Some("foo"));
714 assert_eq!(seq.optional_next::<&str>().unwrap(), Some("bar"));
715
716 let params = Params::new(Some(r#"[]"#));
717 let mut seq = params.sequence();
718 assert!(seq.optional_next::<&str>().unwrap().is_none());
719
720 let params = Params::new(Some(r#" [] "#));
721 let mut seq = params.sequence();
722 assert!(seq.optional_next::<&str>().unwrap().is_none());
723
724 let params = Params::new(Some(r#"{}"#));
725 let mut seq = params.sequence();
726 assert!(seq.optional_next::<&str>().is_err(), "JSON object not supported by RpcSequence");
727
728 let params = Params::new(Some(r#"[12, "[]", [], {}]"#));
729 let mut seq = params.sequence();
730 assert_eq!(seq.optional_next::<u64>().unwrap(), Some(12));
731 assert_eq!(seq.optional_next::<&str>().unwrap(), Some("[]"));
732 assert_eq!(seq.optional_next::<Vec<u8>>().unwrap(), Some(vec![]));
733 assert_eq!(seq.optional_next::<serde_json::Value>().unwrap(), Some(serde_json::json!({})));
734 }
735
736 #[test]
737 fn params_sequence_optional_nesting_works() {
738 let nested = Params::new(Some(r#"[1, [2], [3, 4], [[5], [6,7], []], {"named":7}]"#));
739 let mut seq = nested.sequence();
740 assert_eq!(seq.optional_next::<i8>().unwrap(), Some(1));
741 assert_eq!(seq.optional_next::<[i8; 1]>().unwrap(), Some([2]));
742 assert_eq!(seq.optional_next::<Vec<u16>>().unwrap(), Some(vec![3, 4]));
743 assert_eq!(
744 seq.optional_next::<Vec<Vec<u32>>>().unwrap(),
745 Some(vec![vec![5], vec![6, 7], vec![]])
746 );
747 assert_eq!(
748 seq.optional_next::<serde_json::Value>().unwrap(),
749 Some(serde_json::json!({"named":7}))
750 );
751 }
752}