@@ -16,7 +16,8 @@ use crate::{
1616
1717#[ derive( Debug , Clone , PartialEq , Eq , Hash , Serialize , Deserialize ) ]
1818#[ serde( rename_all = "camelCase" ) ]
19- pub struct LatestPriceRequest {
19+ pub struct LatestPriceRequestRepr {
20+ // Either price feed ids or symbols must be specified.
2021 pub price_feed_ids : Option < Vec < PriceFeedId > > ,
2122 pub symbols : Option < Vec < String > > ,
2223 pub properties : Vec < PriceFeedProperty > ,
@@ -32,9 +33,55 @@ pub struct LatestPriceRequest {
3233 pub channel : Channel ,
3334}
3435
36+ #[ derive( Debug , Clone , PartialEq , Eq , Hash , Serialize ) ]
37+ #[ serde( rename_all = "camelCase" ) ]
38+ pub struct LatestPriceRequest ( LatestPriceRequestRepr ) ;
39+
40+ impl < ' de > Deserialize < ' de > for LatestPriceRequest {
41+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
42+ where
43+ D : serde:: Deserializer < ' de > ,
44+ {
45+ let value = LatestPriceRequestRepr :: deserialize ( deserializer) ?;
46+ Self :: new ( value) . map_err ( Error :: custom)
47+ }
48+ }
49+
50+ impl LatestPriceRequest {
51+ pub fn new ( value : LatestPriceRequestRepr ) -> Result < Self , & ' static str > {
52+ validate_price_feed_ids_or_symbols ( & value. price_feed_ids , & value. symbols ) ?;
53+ validate_optional_nonempty_vec_has_unique_elements (
54+ & value. price_feed_ids ,
55+ "no price feed ids specified" ,
56+ "duplicate price feed ids specified" ,
57+ ) ?;
58+ validate_optional_nonempty_vec_has_unique_elements (
59+ & value. symbols ,
60+ "no symbols specified" ,
61+ "duplicate symbols specified" ,
62+ ) ?;
63+ validate_formats ( & value. formats ) ?;
64+ validate_properties ( & value. properties ) ?;
65+ Ok ( Self ( value) )
66+ }
67+ }
68+
69+ impl Deref for LatestPriceRequest {
70+ type Target = LatestPriceRequestRepr ;
71+
72+ fn deref ( & self ) -> & Self :: Target {
73+ & self . 0
74+ }
75+ }
76+ impl DerefMut for LatestPriceRequest {
77+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
78+ & mut self . 0
79+ }
80+ }
81+
3582#[ derive( Debug , Clone , PartialEq , Eq , Hash , Serialize , Deserialize ) ]
3683#[ serde( rename_all = "camelCase" ) ]
37- pub struct PriceRequest {
84+ pub struct PriceRequestRepr {
3885 pub timestamp : TimestampUs ,
3986 // Either price feed ids or symbols must be specified.
4087 pub price_feed_ids : Option < Vec < PriceFeedId > > ,
@@ -50,6 +97,52 @@ pub struct PriceRequest {
5097 pub channel : Channel ,
5198}
5299
100+ #[ derive( Debug , Clone , PartialEq , Eq , Hash , Serialize ) ]
101+ #[ serde( rename_all = "camelCase" ) ]
102+ pub struct PriceRequest ( PriceRequestRepr ) ;
103+
104+ impl < ' de > Deserialize < ' de > for PriceRequest {
105+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
106+ where
107+ D : serde:: Deserializer < ' de > ,
108+ {
109+ let value = PriceRequestRepr :: deserialize ( deserializer) ?;
110+ Self :: new ( value) . map_err ( Error :: custom)
111+ }
112+ }
113+
114+ impl PriceRequest {
115+ pub fn new ( value : PriceRequestRepr ) -> Result < Self , & ' static str > {
116+ validate_price_feed_ids_or_symbols ( & value. price_feed_ids , & value. symbols ) ?;
117+ validate_optional_nonempty_vec_has_unique_elements (
118+ & value. price_feed_ids ,
119+ "no price feed ids specified" ,
120+ "duplicate price feed ids specified" ,
121+ ) ?;
122+ validate_optional_nonempty_vec_has_unique_elements (
123+ & value. symbols ,
124+ "no symbols specified" ,
125+ "duplicate symbols specified" ,
126+ ) ?;
127+ validate_formats ( & value. formats ) ?;
128+ validate_properties ( & value. properties ) ?;
129+ Ok ( Self ( value) )
130+ }
131+ }
132+
133+ impl Deref for PriceRequest {
134+ type Target = PriceRequestRepr ;
135+
136+ fn deref ( & self ) -> & Self :: Target {
137+ & self . 0
138+ }
139+ }
140+ impl DerefMut for PriceRequest {
141+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
142+ & mut self . 0
143+ }
144+ }
145+
53146#[ derive( Debug , Clone , PartialEq , Eq , Hash , Serialize , Deserialize ) ]
54147#[ serde( rename_all = "camelCase" ) ]
55148pub struct ReducePriceRequest {
@@ -221,40 +314,19 @@ impl<'de> Deserialize<'de> for SubscriptionParams {
221314
222315impl SubscriptionParams {
223316 pub fn new ( value : SubscriptionParamsRepr ) -> Result < Self , & ' static str > {
224- if value. price_feed_ids . is_none ( ) && value. symbols . is_none ( ) {
225- return Err ( "either price feed ids or symbols must be specified" ) ;
226- }
227- if value. price_feed_ids . is_some ( ) && value. symbols . is_some ( ) {
228- return Err ( "either price feed ids or symbols must be specified, not both" ) ;
229- }
230-
231- if let Some ( ref ids) = value. price_feed_ids {
232- if ids. is_empty ( ) {
233- return Err ( "no price feed ids specified" ) ;
234- }
235- if !ids. iter ( ) . all_unique ( ) {
236- return Err ( "duplicate price feed ids specified" ) ;
237- }
238- }
239-
240- if let Some ( ref symbols) = value. symbols {
241- if symbols. is_empty ( ) {
242- return Err ( "no symbols specified" ) ;
243- }
244- if !symbols. iter ( ) . all_unique ( ) {
245- return Err ( "duplicate symbols specified" ) ;
246- }
247- }
248-
249- if !value. formats . iter ( ) . all_unique ( ) {
250- return Err ( "duplicate formats or chains specified" ) ;
251- }
252- if value. properties . is_empty ( ) {
253- return Err ( "no properties specified" ) ;
254- }
255- if !value. properties . iter ( ) . all_unique ( ) {
256- return Err ( "duplicate properties specified" ) ;
257- }
317+ validate_price_feed_ids_or_symbols ( & value. price_feed_ids , & value. symbols ) ?;
318+ validate_optional_nonempty_vec_has_unique_elements (
319+ & value. price_feed_ids ,
320+ "no price feed ids specified" ,
321+ "duplicate price feed ids specified" ,
322+ ) ?;
323+ validate_optional_nonempty_vec_has_unique_elements (
324+ & value. symbols ,
325+ "no symbols specified" ,
326+ "duplicate symbols specified" ,
327+ ) ?;
328+ validate_formats ( & value. formats ) ?;
329+ validate_properties ( & value. properties ) ?;
258330 Ok ( Self ( value) )
259331 }
260332}
@@ -467,6 +539,7 @@ pub struct SubscribedResponse {
467539#[ serde( rename_all = "camelCase" ) ]
468540pub struct InvalidFeedSubscriptionDetails {
469541 pub unknown_ids : Vec < PriceFeedId > ,
542+ pub unknown_symbols : Vec < String > ,
470543 pub unsupported_channels : Vec < PriceFeedId > ,
471544 pub unstable : Vec < PriceFeedId > ,
472545}
@@ -511,3 +584,53 @@ pub struct StreamUpdatedResponse {
511584 #[ serde( flatten) ]
512585 pub payload : JsonUpdate ,
513586}
587+
588+ // Common validation functions
589+ fn validate_price_feed_ids_or_symbols (
590+ price_feed_ids : & Option < Vec < PriceFeedId > > ,
591+ symbols : & Option < Vec < String > > ,
592+ ) -> Result < ( ) , & ' static str > {
593+ if price_feed_ids. is_none ( ) && symbols. is_none ( ) {
594+ return Err ( "either price feed ids or symbols must be specified" ) ;
595+ }
596+ if price_feed_ids. is_some ( ) && symbols. is_some ( ) {
597+ return Err ( "either price feed ids or symbols must be specified, not both" ) ;
598+ }
599+ Ok ( ( ) )
600+ }
601+
602+ fn validate_optional_nonempty_vec_has_unique_elements < T > (
603+ vec : & Option < Vec < T > > ,
604+ empty_msg : & ' static str ,
605+ duplicate_msg : & ' static str ,
606+ ) -> Result < ( ) , & ' static str >
607+ where
608+ T : Eq + std:: hash:: Hash ,
609+ {
610+ if let Some ( ref items) = vec {
611+ if items. is_empty ( ) {
612+ return Err ( empty_msg) ;
613+ }
614+ if !items. iter ( ) . all_unique ( ) {
615+ return Err ( duplicate_msg) ;
616+ }
617+ }
618+ Ok ( ( ) )
619+ }
620+
621+ fn validate_properties ( properties : & [ PriceFeedProperty ] ) -> Result < ( ) , & ' static str > {
622+ if properties. is_empty ( ) {
623+ return Err ( "no properties specified" ) ;
624+ }
625+ if !properties. iter ( ) . all_unique ( ) {
626+ return Err ( "duplicate properties specified" ) ;
627+ }
628+ Ok ( ( ) )
629+ }
630+
631+ fn validate_formats ( formats : & [ Format ] ) -> Result < ( ) , & ' static str > {
632+ if !formats. iter ( ) . all_unique ( ) {
633+ return Err ( "duplicate formats or chains specified" ) ;
634+ }
635+ Ok ( ( ) )
636+ }
0 commit comments