Skip to main content

jsonrpsee_types/
params.rs

1// Copyright 2019-2021 Parity Technologies (UK) Ltd.
2//
3// Permission is hereby granted, free of charge, to any
4// person obtaining a copy of this software and associated
5// documentation files (the "Software"), to deal in the
6// Software without restriction, including without
7// limitation the rights to use, copy, modify, merge,
8// publish, distribute, sublicense, and/or sell copies of
9// the Software, and to permit persons to whom the Software
10// is furnished to do so, subject to the following
11// conditions:
12//
13// The above copyright notice and this permission notice
14// shall be included in all copies or substantial portions
15// of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25// DEALINGS IN THE SOFTWARE.
26
27//! Types to handle JSON-RPC request parameters according to the [spec](https://www.jsonrpc.org/specification#parameter_structures).
28//! Some types come with a "*Ser" variant that implements [`serde::Serialize`]; these are used in
29//! the client.
30
31use 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/// JSON-RPC v2 marker type.
46#[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/// Parameters sent with an incoming JSON-RPC request.
88///
89/// The data containing the params is a `Cow<&str>` and can either be a borrowed `&str` of JSON from
90/// an incoming [`super::request::Request`] (which in turn borrows it from the input buffer that is
91/// shared between requests); or, it can be an owned [`String`].
92#[derive(Clone, Debug)]
93pub struct Params<'a>(Option<Cow<'a, str>>);
94
95impl<'a> Params<'a> {
96    /// Create params
97    pub fn new(raw: Option<&'a str>) -> Self {
98        Self(raw.map(|r| r.trim().into()))
99    }
100
101    /// Obtain a sequence parser, [`ParamsSequence`].
102    ///
103    /// This allows sequential parsing of the incoming params, using an `Iterator`-style API and is
104    /// useful when the RPC request has optional parameters at the tail that may or may not be
105    /// present.
106    pub fn sequence(&self) -> ParamsSequence<'_> {
107        let json = match self.0.as_ref() {
108            // It's assumed that params is `[a,b,c]`, if empty regard as no params.
109            Some(json) if json == "[]" => "",
110            Some(json) => json,
111            None => "",
112        };
113        ParamsSequence(json)
114    }
115
116    /// Attempt to parse all parameters as an array or map into type `T`.
117    pub fn parse<T>(&'a self) -> Result<T, ErrorObjectOwned>
118    where
119        T: Deserialize<'a>,
120    {
121        // NOTE(niklasad1): Option::None is serialized as `null` so we provide that here.
122        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    /// Attempt to parse parameters as an array of a single value of type `T`, and returns that
127    /// value.
128    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    /// Convert `Params<'a>` to `Params<'static>` so that it can be moved across threads.
136    ///
137    /// This will cause an allocation if the params internally are using a borrowed JSON slice.
138    pub fn into_owned(self) -> Params<'static> {
139        Params(self.0.map(|s| Cow::Owned(s.into_owned())))
140    }
141
142    /// Return the length of underlying JSON string in number of bytes.
143    pub fn len_bytes(&self) -> usize {
144        match self.0 {
145            Some(ref cow) => cow.len(),
146            None => 0,
147        }
148    }
149
150    /// Return the underlying JSON string as a `&str`.
151    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/// An `Iterator`-like parser for a sequence of [`Params`].
160///
161/// This will parse the params one at a time, and allows for graceful handling of optional
162/// parameters at the tail; other use cases are likely better served by [`Params::parse`]. The
163/// reason this is not an actual [`Iterator`] is that params parsing (often) yields values of
164/// different types.
165///
166/// Regards empty array `[]` as no parameters provided.
167#[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    /// Parse the next parameter to type `T`
205    ///
206    /// ```
207    /// # use jsonrpsee_types::params::Params;
208    /// let params = Params::new(Some(r#"[true, 10, "foo"]"#));
209    /// let mut seq = params.sequence();
210    ///
211    /// let a: bool = seq.next().unwrap();
212    /// let b: i32 = seq.next().unwrap();
213    /// let c: &str = seq.next().unwrap();
214    ///
215    /// assert_eq!(a, true);
216    /// assert_eq!(b, 10);
217    /// assert_eq!(c, "foo");
218    /// ```
219    #[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    /// Parse the next optional parameter to type `Option<T>`.
231    ///
232    /// The result will be `None` for `null`, and for missing values in the supplied JSON array.
233    ///
234    /// ```
235    /// # use jsonrpsee_types::params::Params;
236    /// let params = Params::new(Some(r#"[1, 2, null]"#));
237    /// let mut seq = params.sequence();
238    ///
239    /// let params: [Option<u32>; 4] = [
240    ///     seq.optional_next().unwrap(),
241    ///     seq.optional_next().unwrap(),
242    ///     seq.optional_next().unwrap(),
243    ///     seq.optional_next().unwrap(),
244    /// ];
245    ///
246    /// assert_eq!(params, [Some(1), Some(2), None, None]);
247    /// ```
248    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/// Id of a subscription, communicated by the server.
260#[derive(Debug, PartialEq, Clone, Hash, Eq, Serialize)]
261#[serde(untagged)]
262pub enum SubscriptionId<'a> {
263    /// Numeric id
264    Num(u64),
265    /// String id
266    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    /// Convert `SubscriptionId<'a>` to `SubscriptionId<'static>` so that it can be moved across
310    /// threads.
311    ///
312    /// This can cause an allocation if the id is a string.
313    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
356/// Parses the id without buffering it: the untagged derive would first copy a peer-supplied array
357/// or object into an intermediate tree before rejecting it.
358impl<'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/// Request Id
368#[derive(Debug, PartialEq, Clone, Hash, Eq, Serialize, PartialOrd, Ord)]
369#[serde(untagged)]
370pub enum Id<'a> {
371    /// Null
372    Null,
373    /// Numeric id
374    Number(u64),
375    /// String id
376    Str(Cow<'a, str>),
377}
378
379impl Id<'_> {
380    /// If the Id is a number, returns the associated number. Returns None otherwise.
381    pub fn as_number(&self) -> Option<&u64> {
382        match self {
383            Self::Number(n) => Some(n),
384            _ => None,
385        }
386    }
387
388    /// If the Id is a String, returns the associated str. Returns None otherwise.
389    pub fn as_str(&self) -> Option<&str> {
390        match self {
391            Self::Str(s) => Some(s.as_ref()),
392            _ => None,
393        }
394    }
395
396    /// Convert `Id<'a>` to `Id<'static>` so that it can be moved across threads.
397    ///
398    /// This can cause an allocation if the id is a string.
399    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
457/// Parses the id without buffering it: the untagged derive would first copy a peer-supplied array
458/// or object into an intermediate tree before rejecting it.
459impl<'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        // Escapes can't be borrowed from the input.
532        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        // It's ok to parse the params again.
621        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        // The fact that it was deserialized is enough.
629        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        // Escapes can't be borrowed from the input.
653        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        // The unsubscribe path parses the id out of the params.
681        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}