Skip to main content

stripe_shared/
issuing_network_token_wallet_provider.rs

1#[derive(Clone, Eq, PartialEq)]
2#[cfg_attr(not(feature = "redact-generated-debug"), derive(Debug))]
3#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
4#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
5pub struct IssuingNetworkTokenWalletProvider {
6    /// The wallet provider-given account ID of the digital wallet the token belongs to.
7    pub account_id: Option<String>,
8    /// An evaluation on the trustworthiness of the wallet account between 1 and 5.
9    /// A higher score indicates more trustworthy.
10    pub account_trust_score: Option<i64>,
11    /// The method used for tokenizing a card.
12    pub card_number_source: Option<IssuingNetworkTokenWalletProviderCardNumberSource>,
13    pub cardholder_address: Option<stripe_shared::IssuingNetworkTokenAddress>,
14    /// The name of the cardholder tokenizing the card.
15    pub cardholder_name: Option<String>,
16    /// An evaluation on the trustworthiness of the device. A higher score indicates more trustworthy.
17    pub device_trust_score: Option<i64>,
18    /// The hashed email address of the cardholder's account with the wallet provider.
19    pub hashed_account_email_address: Option<String>,
20    /// The reasons for suggested tokenization given by the card network.
21    pub reason_codes: Option<Vec<IssuingNetworkTokenWalletProviderReasonCodes>>,
22    /// The recommendation on responding to the tokenization request.
23    pub suggested_decision: Option<IssuingNetworkTokenWalletProviderSuggestedDecision>,
24    /// The version of the standard for mapping reason codes followed by the wallet provider.
25    pub suggested_decision_version: Option<String>,
26}
27#[cfg(feature = "redact-generated-debug")]
28impl std::fmt::Debug for IssuingNetworkTokenWalletProvider {
29    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
30        f.debug_struct("IssuingNetworkTokenWalletProvider").finish_non_exhaustive()
31    }
32}
33#[doc(hidden)]
34pub struct IssuingNetworkTokenWalletProviderBuilder {
35    account_id: Option<Option<String>>,
36    account_trust_score: Option<Option<i64>>,
37    card_number_source: Option<Option<IssuingNetworkTokenWalletProviderCardNumberSource>>,
38    cardholder_address: Option<Option<stripe_shared::IssuingNetworkTokenAddress>>,
39    cardholder_name: Option<Option<String>>,
40    device_trust_score: Option<Option<i64>>,
41    hashed_account_email_address: Option<Option<String>>,
42    reason_codes: Option<Option<Vec<IssuingNetworkTokenWalletProviderReasonCodes>>>,
43    suggested_decision: Option<Option<IssuingNetworkTokenWalletProviderSuggestedDecision>>,
44    suggested_decision_version: Option<Option<String>>,
45}
46
47#[allow(
48    unused_variables,
49    irrefutable_let_patterns,
50    clippy::let_unit_value,
51    clippy::match_single_binding,
52    clippy::single_match
53)]
54const _: () = {
55    use miniserde::de::{Map, Visitor};
56    use miniserde::json::Value;
57    use miniserde::{Deserialize, Result, make_place};
58    use stripe_types::miniserde_helpers::FromValueOpt;
59    use stripe_types::{MapBuilder, ObjectDeser};
60
61    make_place!(Place);
62
63    impl Deserialize for IssuingNetworkTokenWalletProvider {
64        fn begin(out: &mut Option<Self>) -> &mut dyn Visitor {
65            Place::new(out)
66        }
67    }
68
69    struct Builder<'a> {
70        out: &'a mut Option<IssuingNetworkTokenWalletProvider>,
71        builder: IssuingNetworkTokenWalletProviderBuilder,
72    }
73
74    impl Visitor for Place<IssuingNetworkTokenWalletProvider> {
75        fn map(&mut self) -> Result<Box<dyn Map + '_>> {
76            Ok(Box::new(Builder {
77                out: &mut self.out,
78                builder: IssuingNetworkTokenWalletProviderBuilder::deser_default(),
79            }))
80        }
81    }
82
83    impl MapBuilder for IssuingNetworkTokenWalletProviderBuilder {
84        type Out = IssuingNetworkTokenWalletProvider;
85        fn key(&mut self, k: &str) -> Result<&mut dyn Visitor> {
86            Ok(match k {
87                "account_id" => Deserialize::begin(&mut self.account_id),
88                "account_trust_score" => Deserialize::begin(&mut self.account_trust_score),
89                "card_number_source" => Deserialize::begin(&mut self.card_number_source),
90                "cardholder_address" => Deserialize::begin(&mut self.cardholder_address),
91                "cardholder_name" => Deserialize::begin(&mut self.cardholder_name),
92                "device_trust_score" => Deserialize::begin(&mut self.device_trust_score),
93                "hashed_account_email_address" => {
94                    Deserialize::begin(&mut self.hashed_account_email_address)
95                }
96                "reason_codes" => Deserialize::begin(&mut self.reason_codes),
97                "suggested_decision" => Deserialize::begin(&mut self.suggested_decision),
98                "suggested_decision_version" => {
99                    Deserialize::begin(&mut self.suggested_decision_version)
100                }
101                _ => <dyn Visitor>::ignore(),
102            })
103        }
104
105        fn deser_default() -> Self {
106            Self {
107                account_id: Some(None),
108                account_trust_score: Some(None),
109                card_number_source: Some(None),
110                cardholder_address: Some(None),
111                cardholder_name: Some(None),
112                device_trust_score: Some(None),
113                hashed_account_email_address: Some(None),
114                reason_codes: Some(None),
115                suggested_decision: Some(None),
116                suggested_decision_version: Some(None),
117            }
118        }
119
120        fn take_out(&mut self) -> Option<Self::Out> {
121            let (
122                Some(account_id),
123                Some(account_trust_score),
124                Some(card_number_source),
125                Some(cardholder_address),
126                Some(cardholder_name),
127                Some(device_trust_score),
128                Some(hashed_account_email_address),
129                Some(reason_codes),
130                Some(suggested_decision),
131                Some(suggested_decision_version),
132            ) = (
133                self.account_id.take(),
134                self.account_trust_score,
135                self.card_number_source.take(),
136                self.cardholder_address.take(),
137                self.cardholder_name.take(),
138                self.device_trust_score,
139                self.hashed_account_email_address.take(),
140                self.reason_codes.take(),
141                self.suggested_decision.take(),
142                self.suggested_decision_version.take(),
143            )
144            else {
145                return None;
146            };
147            Some(Self::Out {
148                account_id,
149                account_trust_score,
150                card_number_source,
151                cardholder_address,
152                cardholder_name,
153                device_trust_score,
154                hashed_account_email_address,
155                reason_codes,
156                suggested_decision,
157                suggested_decision_version,
158            })
159        }
160    }
161
162    impl Map for Builder<'_> {
163        fn key(&mut self, k: &str) -> Result<&mut dyn Visitor> {
164            self.builder.key(k)
165        }
166
167        fn finish(&mut self) -> Result<()> {
168            *self.out = self.builder.take_out();
169            Ok(())
170        }
171    }
172
173    impl ObjectDeser for IssuingNetworkTokenWalletProvider {
174        type Builder = IssuingNetworkTokenWalletProviderBuilder;
175    }
176
177    impl FromValueOpt for IssuingNetworkTokenWalletProvider {
178        fn from_value(v: Value) -> Option<Self> {
179            let Value::Object(obj) = v else {
180                return None;
181            };
182            let mut b = IssuingNetworkTokenWalletProviderBuilder::deser_default();
183            for (k, v) in obj {
184                match k.as_str() {
185                    "account_id" => b.account_id = FromValueOpt::from_value(v),
186                    "account_trust_score" => b.account_trust_score = FromValueOpt::from_value(v),
187                    "card_number_source" => b.card_number_source = FromValueOpt::from_value(v),
188                    "cardholder_address" => b.cardholder_address = FromValueOpt::from_value(v),
189                    "cardholder_name" => b.cardholder_name = FromValueOpt::from_value(v),
190                    "device_trust_score" => b.device_trust_score = FromValueOpt::from_value(v),
191                    "hashed_account_email_address" => {
192                        b.hashed_account_email_address = FromValueOpt::from_value(v)
193                    }
194                    "reason_codes" => b.reason_codes = FromValueOpt::from_value(v),
195                    "suggested_decision" => b.suggested_decision = FromValueOpt::from_value(v),
196                    "suggested_decision_version" => {
197                        b.suggested_decision_version = FromValueOpt::from_value(v)
198                    }
199                    _ => {}
200                }
201            }
202            b.take_out()
203        }
204    }
205};
206/// The method used for tokenizing a card.
207#[derive(Clone, Eq, PartialEq)]
208#[non_exhaustive]
209pub enum IssuingNetworkTokenWalletProviderCardNumberSource {
210    App,
211    Manual,
212    OnFile,
213    Other,
214    /// An unrecognized value from Stripe. Should not be used as a request parameter.
215    Unknown(String),
216}
217impl IssuingNetworkTokenWalletProviderCardNumberSource {
218    pub fn as_str(&self) -> &str {
219        use IssuingNetworkTokenWalletProviderCardNumberSource::*;
220        match self {
221            App => "app",
222            Manual => "manual",
223            OnFile => "on_file",
224            Other => "other",
225            Unknown(v) => v,
226        }
227    }
228}
229
230impl std::str::FromStr for IssuingNetworkTokenWalletProviderCardNumberSource {
231    type Err = std::convert::Infallible;
232    fn from_str(s: &str) -> Result<Self, Self::Err> {
233        use IssuingNetworkTokenWalletProviderCardNumberSource::*;
234        match s {
235            "app" => Ok(App),
236            "manual" => Ok(Manual),
237            "on_file" => Ok(OnFile),
238            "other" => Ok(Other),
239            v => {
240                tracing::warn!(
241                    "Unknown value '{}' for enum '{}'",
242                    v,
243                    "IssuingNetworkTokenWalletProviderCardNumberSource"
244                );
245                Ok(Unknown(v.to_owned()))
246            }
247        }
248    }
249}
250impl std::fmt::Display for IssuingNetworkTokenWalletProviderCardNumberSource {
251    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
252        f.write_str(self.as_str())
253    }
254}
255
256#[cfg(not(feature = "redact-generated-debug"))]
257impl std::fmt::Debug for IssuingNetworkTokenWalletProviderCardNumberSource {
258    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
259        f.write_str(self.as_str())
260    }
261}
262#[cfg(feature = "redact-generated-debug")]
263impl std::fmt::Debug for IssuingNetworkTokenWalletProviderCardNumberSource {
264    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
265        f.debug_struct(stringify!(IssuingNetworkTokenWalletProviderCardNumberSource))
266            .finish_non_exhaustive()
267    }
268}
269#[cfg(feature = "serialize")]
270impl serde::Serialize for IssuingNetworkTokenWalletProviderCardNumberSource {
271    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
272    where
273        S: serde::Serializer,
274    {
275        serializer.serialize_str(self.as_str())
276    }
277}
278impl miniserde::Deserialize for IssuingNetworkTokenWalletProviderCardNumberSource {
279    fn begin(out: &mut Option<Self>) -> &mut dyn miniserde::de::Visitor {
280        crate::Place::new(out)
281    }
282}
283
284impl miniserde::de::Visitor for crate::Place<IssuingNetworkTokenWalletProviderCardNumberSource> {
285    fn string(&mut self, s: &str) -> miniserde::Result<()> {
286        use std::str::FromStr;
287        self.out = Some(
288            IssuingNetworkTokenWalletProviderCardNumberSource::from_str(s).expect("infallible"),
289        );
290        Ok(())
291    }
292}
293
294stripe_types::impl_from_val_with_from_str!(IssuingNetworkTokenWalletProviderCardNumberSource);
295#[cfg(feature = "deserialize")]
296impl<'de> serde::Deserialize<'de> for IssuingNetworkTokenWalletProviderCardNumberSource {
297    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
298        use std::str::FromStr;
299        let s: std::borrow::Cow<'de, str> = serde::Deserialize::deserialize(deserializer)?;
300        Ok(Self::from_str(&s).expect("infallible"))
301    }
302}
303/// The reasons for suggested tokenization given by the card network.
304#[derive(Clone, Eq, PartialEq)]
305#[non_exhaustive]
306pub enum IssuingNetworkTokenWalletProviderReasonCodes {
307    AccountCardTooNew,
308    AccountRecentlyChanged,
309    AccountTooNew,
310    AccountTooNewSinceLaunch,
311    AdditionalDevice,
312    DataExpired,
313    DeferIdVDecision,
314    DeviceRecentlyLost,
315    GoodActivityHistory,
316    HasSuspendedTokens,
317    HighRisk,
318    InactiveAccount,
319    LongAccountTenure,
320    LowAccountScore,
321    LowDeviceScore,
322    LowPhoneNumberScore,
323    NetworkServiceError,
324    OutsideHomeTerritory,
325    ProvisioningCardholderMismatch,
326    ProvisioningDeviceAndCardholderMismatch,
327    ProvisioningDeviceMismatch,
328    SameDeviceNoPriorAuthentication,
329    SameDeviceSuccessfulPriorAuthentication,
330    SoftwareUpdate,
331    SuspiciousActivity,
332    TooManyDifferentCardholders,
333    TooManyRecentAttempts,
334    TooManyRecentTokens,
335    /// An unrecognized value from Stripe. Should not be used as a request parameter.
336    Unknown(String),
337}
338impl IssuingNetworkTokenWalletProviderReasonCodes {
339    pub fn as_str(&self) -> &str {
340        use IssuingNetworkTokenWalletProviderReasonCodes::*;
341        match self {
342            AccountCardTooNew => "account_card_too_new",
343            AccountRecentlyChanged => "account_recently_changed",
344            AccountTooNew => "account_too_new",
345            AccountTooNewSinceLaunch => "account_too_new_since_launch",
346            AdditionalDevice => "additional_device",
347            DataExpired => "data_expired",
348            DeferIdVDecision => "defer_id_v_decision",
349            DeviceRecentlyLost => "device_recently_lost",
350            GoodActivityHistory => "good_activity_history",
351            HasSuspendedTokens => "has_suspended_tokens",
352            HighRisk => "high_risk",
353            InactiveAccount => "inactive_account",
354            LongAccountTenure => "long_account_tenure",
355            LowAccountScore => "low_account_score",
356            LowDeviceScore => "low_device_score",
357            LowPhoneNumberScore => "low_phone_number_score",
358            NetworkServiceError => "network_service_error",
359            OutsideHomeTerritory => "outside_home_territory",
360            ProvisioningCardholderMismatch => "provisioning_cardholder_mismatch",
361            ProvisioningDeviceAndCardholderMismatch => {
362                "provisioning_device_and_cardholder_mismatch"
363            }
364            ProvisioningDeviceMismatch => "provisioning_device_mismatch",
365            SameDeviceNoPriorAuthentication => "same_device_no_prior_authentication",
366            SameDeviceSuccessfulPriorAuthentication => {
367                "same_device_successful_prior_authentication"
368            }
369            SoftwareUpdate => "software_update",
370            SuspiciousActivity => "suspicious_activity",
371            TooManyDifferentCardholders => "too_many_different_cardholders",
372            TooManyRecentAttempts => "too_many_recent_attempts",
373            TooManyRecentTokens => "too_many_recent_tokens",
374            Unknown(v) => v,
375        }
376    }
377}
378
379impl std::str::FromStr for IssuingNetworkTokenWalletProviderReasonCodes {
380    type Err = std::convert::Infallible;
381    fn from_str(s: &str) -> Result<Self, Self::Err> {
382        use IssuingNetworkTokenWalletProviderReasonCodes::*;
383        match s {
384            "account_card_too_new" => Ok(AccountCardTooNew),
385            "account_recently_changed" => Ok(AccountRecentlyChanged),
386            "account_too_new" => Ok(AccountTooNew),
387            "account_too_new_since_launch" => Ok(AccountTooNewSinceLaunch),
388            "additional_device" => Ok(AdditionalDevice),
389            "data_expired" => Ok(DataExpired),
390            "defer_id_v_decision" => Ok(DeferIdVDecision),
391            "device_recently_lost" => Ok(DeviceRecentlyLost),
392            "good_activity_history" => Ok(GoodActivityHistory),
393            "has_suspended_tokens" => Ok(HasSuspendedTokens),
394            "high_risk" => Ok(HighRisk),
395            "inactive_account" => Ok(InactiveAccount),
396            "long_account_tenure" => Ok(LongAccountTenure),
397            "low_account_score" => Ok(LowAccountScore),
398            "low_device_score" => Ok(LowDeviceScore),
399            "low_phone_number_score" => Ok(LowPhoneNumberScore),
400            "network_service_error" => Ok(NetworkServiceError),
401            "outside_home_territory" => Ok(OutsideHomeTerritory),
402            "provisioning_cardholder_mismatch" => Ok(ProvisioningCardholderMismatch),
403            "provisioning_device_and_cardholder_mismatch" => {
404                Ok(ProvisioningDeviceAndCardholderMismatch)
405            }
406            "provisioning_device_mismatch" => Ok(ProvisioningDeviceMismatch),
407            "same_device_no_prior_authentication" => Ok(SameDeviceNoPriorAuthentication),
408            "same_device_successful_prior_authentication" => {
409                Ok(SameDeviceSuccessfulPriorAuthentication)
410            }
411            "software_update" => Ok(SoftwareUpdate),
412            "suspicious_activity" => Ok(SuspiciousActivity),
413            "too_many_different_cardholders" => Ok(TooManyDifferentCardholders),
414            "too_many_recent_attempts" => Ok(TooManyRecentAttempts),
415            "too_many_recent_tokens" => Ok(TooManyRecentTokens),
416            v => {
417                tracing::warn!(
418                    "Unknown value '{}' for enum '{}'",
419                    v,
420                    "IssuingNetworkTokenWalletProviderReasonCodes"
421                );
422                Ok(Unknown(v.to_owned()))
423            }
424        }
425    }
426}
427impl std::fmt::Display for IssuingNetworkTokenWalletProviderReasonCodes {
428    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
429        f.write_str(self.as_str())
430    }
431}
432
433#[cfg(not(feature = "redact-generated-debug"))]
434impl std::fmt::Debug for IssuingNetworkTokenWalletProviderReasonCodes {
435    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
436        f.write_str(self.as_str())
437    }
438}
439#[cfg(feature = "redact-generated-debug")]
440impl std::fmt::Debug for IssuingNetworkTokenWalletProviderReasonCodes {
441    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
442        f.debug_struct(stringify!(IssuingNetworkTokenWalletProviderReasonCodes))
443            .finish_non_exhaustive()
444    }
445}
446#[cfg(feature = "serialize")]
447impl serde::Serialize for IssuingNetworkTokenWalletProviderReasonCodes {
448    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
449    where
450        S: serde::Serializer,
451    {
452        serializer.serialize_str(self.as_str())
453    }
454}
455impl miniserde::Deserialize for IssuingNetworkTokenWalletProviderReasonCodes {
456    fn begin(out: &mut Option<Self>) -> &mut dyn miniserde::de::Visitor {
457        crate::Place::new(out)
458    }
459}
460
461impl miniserde::de::Visitor for crate::Place<IssuingNetworkTokenWalletProviderReasonCodes> {
462    fn string(&mut self, s: &str) -> miniserde::Result<()> {
463        use std::str::FromStr;
464        self.out =
465            Some(IssuingNetworkTokenWalletProviderReasonCodes::from_str(s).expect("infallible"));
466        Ok(())
467    }
468}
469
470stripe_types::impl_from_val_with_from_str!(IssuingNetworkTokenWalletProviderReasonCodes);
471#[cfg(feature = "deserialize")]
472impl<'de> serde::Deserialize<'de> for IssuingNetworkTokenWalletProviderReasonCodes {
473    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
474        use std::str::FromStr;
475        let s: std::borrow::Cow<'de, str> = serde::Deserialize::deserialize(deserializer)?;
476        Ok(Self::from_str(&s).expect("infallible"))
477    }
478}
479/// The recommendation on responding to the tokenization request.
480#[derive(Clone, Eq, PartialEq)]
481#[non_exhaustive]
482pub enum IssuingNetworkTokenWalletProviderSuggestedDecision {
483    Approve,
484    Decline,
485    RequireAuth,
486    /// An unrecognized value from Stripe. Should not be used as a request parameter.
487    Unknown(String),
488}
489impl IssuingNetworkTokenWalletProviderSuggestedDecision {
490    pub fn as_str(&self) -> &str {
491        use IssuingNetworkTokenWalletProviderSuggestedDecision::*;
492        match self {
493            Approve => "approve",
494            Decline => "decline",
495            RequireAuth => "require_auth",
496            Unknown(v) => v,
497        }
498    }
499}
500
501impl std::str::FromStr for IssuingNetworkTokenWalletProviderSuggestedDecision {
502    type Err = std::convert::Infallible;
503    fn from_str(s: &str) -> Result<Self, Self::Err> {
504        use IssuingNetworkTokenWalletProviderSuggestedDecision::*;
505        match s {
506            "approve" => Ok(Approve),
507            "decline" => Ok(Decline),
508            "require_auth" => Ok(RequireAuth),
509            v => {
510                tracing::warn!(
511                    "Unknown value '{}' for enum '{}'",
512                    v,
513                    "IssuingNetworkTokenWalletProviderSuggestedDecision"
514                );
515                Ok(Unknown(v.to_owned()))
516            }
517        }
518    }
519}
520impl std::fmt::Display for IssuingNetworkTokenWalletProviderSuggestedDecision {
521    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
522        f.write_str(self.as_str())
523    }
524}
525
526#[cfg(not(feature = "redact-generated-debug"))]
527impl std::fmt::Debug for IssuingNetworkTokenWalletProviderSuggestedDecision {
528    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
529        f.write_str(self.as_str())
530    }
531}
532#[cfg(feature = "redact-generated-debug")]
533impl std::fmt::Debug for IssuingNetworkTokenWalletProviderSuggestedDecision {
534    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
535        f.debug_struct(stringify!(IssuingNetworkTokenWalletProviderSuggestedDecision))
536            .finish_non_exhaustive()
537    }
538}
539#[cfg(feature = "serialize")]
540impl serde::Serialize for IssuingNetworkTokenWalletProviderSuggestedDecision {
541    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
542    where
543        S: serde::Serializer,
544    {
545        serializer.serialize_str(self.as_str())
546    }
547}
548impl miniserde::Deserialize for IssuingNetworkTokenWalletProviderSuggestedDecision {
549    fn begin(out: &mut Option<Self>) -> &mut dyn miniserde::de::Visitor {
550        crate::Place::new(out)
551    }
552}
553
554impl miniserde::de::Visitor for crate::Place<IssuingNetworkTokenWalletProviderSuggestedDecision> {
555    fn string(&mut self, s: &str) -> miniserde::Result<()> {
556        use std::str::FromStr;
557        self.out = Some(
558            IssuingNetworkTokenWalletProviderSuggestedDecision::from_str(s).expect("infallible"),
559        );
560        Ok(())
561    }
562}
563
564stripe_types::impl_from_val_with_from_str!(IssuingNetworkTokenWalletProviderSuggestedDecision);
565#[cfg(feature = "deserialize")]
566impl<'de> serde::Deserialize<'de> for IssuingNetworkTokenWalletProviderSuggestedDecision {
567    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
568        use std::str::FromStr;
569        let s: std::borrow::Cow<'de, str> = serde::Deserialize::deserialize(deserializer)?;
570        Ok(Self::from_str(&s).expect("infallible"))
571    }
572}