stripe_shared/
price.rs

1/// Prices define the unit cost, currency, and (optional) billing cycle for both recurring and one-time purchases of products.
2/// [Products](https://stripe.com/docs/api#products) help you track inventory or provisioning, and prices help you track payment terms.
3/// Different physical goods or levels of service should be represented by products, and pricing options should be represented by prices.
4/// This approach lets you change prices without having to change your provisioning scheme.
5///
6/// For example, you might have a single "gold" product that has prices for $10/month, $100/year, and €9 once.
7///
8/// Related guides: [Set up a subscription](https://stripe.com/docs/billing/subscriptions/set-up-subscription), [create an invoice](https://stripe.com/docs/billing/invoices/create), and more about [products and prices](https://stripe.com/docs/products-prices/overview).
9///
10/// For more details see <<https://stripe.com/docs/api/prices/object>>.
11#[derive(Clone, Debug)]
12#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
13pub struct Price {
14    /// Whether the price can be used for new purchases.
15    pub active: bool,
16    /// Describes how to compute the price per period.
17    /// Either `per_unit` or `tiered`.
18    /// `per_unit` indicates that the fixed amount (specified in `unit_amount` or `unit_amount_decimal`) will be charged per unit in `quantity` (for prices with `usage_type=licensed`), or per unit of total usage (for prices with `usage_type=metered`).
19    /// `tiered` indicates that the unit pricing will be computed using a tiering strategy as defined using the `tiers` and `tiers_mode` attributes.
20    pub billing_scheme: stripe_shared::PriceBillingScheme,
21    /// Time at which the object was created. Measured in seconds since the Unix epoch.
22    pub created: stripe_types::Timestamp,
23    /// Three-letter [ISO currency code](https://www.iso.org/iso-4217-currency-codes.html), in lowercase.
24    /// Must be a [supported currency](https://stripe.com/docs/currencies).
25    pub currency: stripe_types::Currency,
26    /// Prices defined in each available currency option.
27    /// Each key must be a three-letter [ISO currency code](https://www.iso.org/iso-4217-currency-codes.html) and a [supported currency](https://stripe.com/docs/currencies).
28    pub currency_options:
29        Option<std::collections::HashMap<stripe_types::Currency, stripe_shared::CurrencyOption>>,
30    /// When set, provides configuration for the amount to be adjusted by the customer during Checkout Sessions and Payment Links.
31    pub custom_unit_amount: Option<stripe_shared::CustomUnitAmount>,
32    /// Unique identifier for the object.
33    pub id: stripe_shared::PriceId,
34    /// Has the value `true` if the object exists in live mode or the value `false` if the object exists in test mode.
35    pub livemode: bool,
36    /// A lookup key used to retrieve prices dynamically from a static string.
37    /// This may be up to 200 characters.
38    pub lookup_key: Option<String>,
39    /// Set of [key-value pairs](https://stripe.com/docs/api/metadata) that you can attach to an object.
40    /// This can be useful for storing additional information about the object in a structured format.
41    pub metadata: std::collections::HashMap<String, String>,
42    /// A brief description of the price, hidden from customers.
43    pub nickname: Option<String>,
44    /// The ID of the product this price is associated with.
45    pub product: stripe_types::Expandable<stripe_shared::Product>,
46    /// The recurring components of a price such as `interval` and `usage_type`.
47    pub recurring: Option<stripe_shared::Recurring>,
48    /// Only required if a [default tax behavior](https://stripe.com/docs/tax/products-prices-tax-categories-tax-behavior#setting-a-default-tax-behavior-(recommended)) was not provided in the Stripe Tax settings.
49    /// Specifies whether the price is considered inclusive of taxes or exclusive of taxes.
50    /// One of `inclusive`, `exclusive`, or `unspecified`.
51    /// Once specified as either `inclusive` or `exclusive`, it cannot be changed.
52    pub tax_behavior: Option<stripe_shared::PriceTaxBehavior>,
53    /// Each element represents a pricing tier.
54    /// This parameter requires `billing_scheme` to be set to `tiered`.
55    /// See also the documentation for `billing_scheme`.
56    pub tiers: Option<Vec<stripe_shared::PriceTier>>,
57    /// Defines if the tiering price should be `graduated` or `volume` based.
58    /// In `volume`-based tiering, the maximum quantity within a period determines the per unit price.
59    /// In `graduated` tiering, pricing can change as the quantity grows.
60    pub tiers_mode: Option<stripe_shared::PriceTiersMode>,
61    /// Apply a transformation to the reported usage or set quantity before computing the amount billed.
62    /// Cannot be combined with `tiers`.
63    pub transform_quantity: Option<stripe_shared::TransformQuantity>,
64    /// One of `one_time` or `recurring` depending on whether the price is for a one-time purchase or a recurring (subscription) purchase.
65    #[cfg_attr(feature = "deserialize", serde(rename = "type"))]
66    pub type_: stripe_shared::PriceType,
67    /// The unit amount in cents (or local equivalent) to be charged, represented as a whole integer if possible.
68    /// Only set if `billing_scheme=per_unit`.
69    pub unit_amount: Option<i64>,
70    /// The unit amount in cents (or local equivalent) to be charged, represented as a decimal string with at most 12 decimal places.
71    /// Only set if `billing_scheme=per_unit`.
72    pub unit_amount_decimal: Option<String>,
73}
74#[doc(hidden)]
75pub struct PriceBuilder {
76    active: Option<bool>,
77    billing_scheme: Option<stripe_shared::PriceBillingScheme>,
78    created: Option<stripe_types::Timestamp>,
79    currency: Option<stripe_types::Currency>,
80    currency_options: Option<
81        Option<std::collections::HashMap<stripe_types::Currency, stripe_shared::CurrencyOption>>,
82    >,
83    custom_unit_amount: Option<Option<stripe_shared::CustomUnitAmount>>,
84    id: Option<stripe_shared::PriceId>,
85    livemode: Option<bool>,
86    lookup_key: Option<Option<String>>,
87    metadata: Option<std::collections::HashMap<String, String>>,
88    nickname: Option<Option<String>>,
89    product: Option<stripe_types::Expandable<stripe_shared::Product>>,
90    recurring: Option<Option<stripe_shared::Recurring>>,
91    tax_behavior: Option<Option<stripe_shared::PriceTaxBehavior>>,
92    tiers: Option<Option<Vec<stripe_shared::PriceTier>>>,
93    tiers_mode: Option<Option<stripe_shared::PriceTiersMode>>,
94    transform_quantity: Option<Option<stripe_shared::TransformQuantity>>,
95    type_: Option<stripe_shared::PriceType>,
96    unit_amount: Option<Option<i64>>,
97    unit_amount_decimal: Option<Option<String>>,
98}
99
100#[allow(
101    unused_variables,
102    irrefutable_let_patterns,
103    clippy::let_unit_value,
104    clippy::match_single_binding,
105    clippy::single_match
106)]
107const _: () = {
108    use miniserde::de::{Map, Visitor};
109    use miniserde::json::Value;
110    use miniserde::{Deserialize, Result, make_place};
111    use stripe_types::miniserde_helpers::FromValueOpt;
112    use stripe_types::{MapBuilder, ObjectDeser};
113
114    make_place!(Place);
115
116    impl Deserialize for Price {
117        fn begin(out: &mut Option<Self>) -> &mut dyn Visitor {
118            Place::new(out)
119        }
120    }
121
122    struct Builder<'a> {
123        out: &'a mut Option<Price>,
124        builder: PriceBuilder,
125    }
126
127    impl Visitor for Place<Price> {
128        fn map(&mut self) -> Result<Box<dyn Map + '_>> {
129            Ok(Box::new(Builder { out: &mut self.out, builder: PriceBuilder::deser_default() }))
130        }
131    }
132
133    impl MapBuilder for PriceBuilder {
134        type Out = Price;
135        fn key(&mut self, k: &str) -> Result<&mut dyn Visitor> {
136            Ok(match k {
137                "active" => Deserialize::begin(&mut self.active),
138                "billing_scheme" => Deserialize::begin(&mut self.billing_scheme),
139                "created" => Deserialize::begin(&mut self.created),
140                "currency" => Deserialize::begin(&mut self.currency),
141                "currency_options" => Deserialize::begin(&mut self.currency_options),
142                "custom_unit_amount" => Deserialize::begin(&mut self.custom_unit_amount),
143                "id" => Deserialize::begin(&mut self.id),
144                "livemode" => Deserialize::begin(&mut self.livemode),
145                "lookup_key" => Deserialize::begin(&mut self.lookup_key),
146                "metadata" => Deserialize::begin(&mut self.metadata),
147                "nickname" => Deserialize::begin(&mut self.nickname),
148                "product" => Deserialize::begin(&mut self.product),
149                "recurring" => Deserialize::begin(&mut self.recurring),
150                "tax_behavior" => Deserialize::begin(&mut self.tax_behavior),
151                "tiers" => Deserialize::begin(&mut self.tiers),
152                "tiers_mode" => Deserialize::begin(&mut self.tiers_mode),
153                "transform_quantity" => Deserialize::begin(&mut self.transform_quantity),
154                "type" => Deserialize::begin(&mut self.type_),
155                "unit_amount" => Deserialize::begin(&mut self.unit_amount),
156                "unit_amount_decimal" => Deserialize::begin(&mut self.unit_amount_decimal),
157                _ => <dyn Visitor>::ignore(),
158            })
159        }
160
161        fn deser_default() -> Self {
162            Self {
163                active: Deserialize::default(),
164                billing_scheme: Deserialize::default(),
165                created: Deserialize::default(),
166                currency: Deserialize::default(),
167                currency_options: Deserialize::default(),
168                custom_unit_amount: Deserialize::default(),
169                id: Deserialize::default(),
170                livemode: Deserialize::default(),
171                lookup_key: Deserialize::default(),
172                metadata: Deserialize::default(),
173                nickname: Deserialize::default(),
174                product: Deserialize::default(),
175                recurring: Deserialize::default(),
176                tax_behavior: Deserialize::default(),
177                tiers: Deserialize::default(),
178                tiers_mode: Deserialize::default(),
179                transform_quantity: Deserialize::default(),
180                type_: Deserialize::default(),
181                unit_amount: Deserialize::default(),
182                unit_amount_decimal: Deserialize::default(),
183            }
184        }
185
186        fn take_out(&mut self) -> Option<Self::Out> {
187            let (
188                Some(active),
189                Some(billing_scheme),
190                Some(created),
191                Some(currency),
192                Some(currency_options),
193                Some(custom_unit_amount),
194                Some(id),
195                Some(livemode),
196                Some(lookup_key),
197                Some(metadata),
198                Some(nickname),
199                Some(product),
200                Some(recurring),
201                Some(tax_behavior),
202                Some(tiers),
203                Some(tiers_mode),
204                Some(transform_quantity),
205                Some(type_),
206                Some(unit_amount),
207                Some(unit_amount_decimal),
208            ) = (
209                self.active,
210                self.billing_scheme.take(),
211                self.created,
212                self.currency.take(),
213                self.currency_options.take(),
214                self.custom_unit_amount,
215                self.id.take(),
216                self.livemode,
217                self.lookup_key.take(),
218                self.metadata.take(),
219                self.nickname.take(),
220                self.product.take(),
221                self.recurring.take(),
222                self.tax_behavior.take(),
223                self.tiers.take(),
224                self.tiers_mode.take(),
225                self.transform_quantity.take(),
226                self.type_.take(),
227                self.unit_amount,
228                self.unit_amount_decimal.take(),
229            )
230            else {
231                return None;
232            };
233            Some(Self::Out {
234                active,
235                billing_scheme,
236                created,
237                currency,
238                currency_options,
239                custom_unit_amount,
240                id,
241                livemode,
242                lookup_key,
243                metadata,
244                nickname,
245                product,
246                recurring,
247                tax_behavior,
248                tiers,
249                tiers_mode,
250                transform_quantity,
251                type_,
252                unit_amount,
253                unit_amount_decimal,
254            })
255        }
256    }
257
258    impl Map for Builder<'_> {
259        fn key(&mut self, k: &str) -> Result<&mut dyn Visitor> {
260            self.builder.key(k)
261        }
262
263        fn finish(&mut self) -> Result<()> {
264            *self.out = self.builder.take_out();
265            Ok(())
266        }
267    }
268
269    impl ObjectDeser for Price {
270        type Builder = PriceBuilder;
271    }
272
273    impl FromValueOpt for Price {
274        fn from_value(v: Value) -> Option<Self> {
275            let Value::Object(obj) = v else {
276                return None;
277            };
278            let mut b = PriceBuilder::deser_default();
279            for (k, v) in obj {
280                match k.as_str() {
281                    "active" => b.active = FromValueOpt::from_value(v),
282                    "billing_scheme" => b.billing_scheme = FromValueOpt::from_value(v),
283                    "created" => b.created = FromValueOpt::from_value(v),
284                    "currency" => b.currency = FromValueOpt::from_value(v),
285                    "currency_options" => b.currency_options = FromValueOpt::from_value(v),
286                    "custom_unit_amount" => b.custom_unit_amount = FromValueOpt::from_value(v),
287                    "id" => b.id = FromValueOpt::from_value(v),
288                    "livemode" => b.livemode = FromValueOpt::from_value(v),
289                    "lookup_key" => b.lookup_key = FromValueOpt::from_value(v),
290                    "metadata" => b.metadata = FromValueOpt::from_value(v),
291                    "nickname" => b.nickname = FromValueOpt::from_value(v),
292                    "product" => b.product = FromValueOpt::from_value(v),
293                    "recurring" => b.recurring = FromValueOpt::from_value(v),
294                    "tax_behavior" => b.tax_behavior = FromValueOpt::from_value(v),
295                    "tiers" => b.tiers = FromValueOpt::from_value(v),
296                    "tiers_mode" => b.tiers_mode = FromValueOpt::from_value(v),
297                    "transform_quantity" => b.transform_quantity = FromValueOpt::from_value(v),
298                    "type" => b.type_ = FromValueOpt::from_value(v),
299                    "unit_amount" => b.unit_amount = FromValueOpt::from_value(v),
300                    "unit_amount_decimal" => b.unit_amount_decimal = FromValueOpt::from_value(v),
301                    _ => {}
302                }
303            }
304            b.take_out()
305        }
306    }
307};
308#[cfg(feature = "serialize")]
309impl serde::Serialize for Price {
310    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
311        use serde::ser::SerializeStruct;
312        let mut s = s.serialize_struct("Price", 21)?;
313        s.serialize_field("active", &self.active)?;
314        s.serialize_field("billing_scheme", &self.billing_scheme)?;
315        s.serialize_field("created", &self.created)?;
316        s.serialize_field("currency", &self.currency)?;
317        s.serialize_field("currency_options", &self.currency_options)?;
318        s.serialize_field("custom_unit_amount", &self.custom_unit_amount)?;
319        s.serialize_field("id", &self.id)?;
320        s.serialize_field("livemode", &self.livemode)?;
321        s.serialize_field("lookup_key", &self.lookup_key)?;
322        s.serialize_field("metadata", &self.metadata)?;
323        s.serialize_field("nickname", &self.nickname)?;
324        s.serialize_field("product", &self.product)?;
325        s.serialize_field("recurring", &self.recurring)?;
326        s.serialize_field("tax_behavior", &self.tax_behavior)?;
327        s.serialize_field("tiers", &self.tiers)?;
328        s.serialize_field("tiers_mode", &self.tiers_mode)?;
329        s.serialize_field("transform_quantity", &self.transform_quantity)?;
330        s.serialize_field("type", &self.type_)?;
331        s.serialize_field("unit_amount", &self.unit_amount)?;
332        s.serialize_field("unit_amount_decimal", &self.unit_amount_decimal)?;
333
334        s.serialize_field("object", "price")?;
335        s.end()
336    }
337}
338impl stripe_types::Object for Price {
339    type Id = stripe_shared::PriceId;
340    fn id(&self) -> &Self::Id {
341        &self.id
342    }
343
344    fn into_id(self) -> Self::Id {
345        self.id
346    }
347}
348stripe_types::def_id!(PriceId);
349#[derive(Clone, Eq, PartialEq)]
350#[non_exhaustive]
351pub enum PriceBillingScheme {
352    PerUnit,
353    Tiered,
354    /// An unrecognized value from Stripe. Should not be used as a request parameter.
355    Unknown(String),
356}
357impl PriceBillingScheme {
358    pub fn as_str(&self) -> &str {
359        use PriceBillingScheme::*;
360        match self {
361            PerUnit => "per_unit",
362            Tiered => "tiered",
363            Unknown(v) => v,
364        }
365    }
366}
367
368impl std::str::FromStr for PriceBillingScheme {
369    type Err = std::convert::Infallible;
370    fn from_str(s: &str) -> Result<Self, Self::Err> {
371        use PriceBillingScheme::*;
372        match s {
373            "per_unit" => Ok(PerUnit),
374            "tiered" => Ok(Tiered),
375            v => {
376                tracing::warn!("Unknown value '{}' for enum '{}'", v, "PriceBillingScheme");
377                Ok(Unknown(v.to_owned()))
378            }
379        }
380    }
381}
382impl std::fmt::Display for PriceBillingScheme {
383    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
384        f.write_str(self.as_str())
385    }
386}
387
388impl std::fmt::Debug for PriceBillingScheme {
389    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
390        f.write_str(self.as_str())
391    }
392}
393impl serde::Serialize for PriceBillingScheme {
394    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
395    where
396        S: serde::Serializer,
397    {
398        serializer.serialize_str(self.as_str())
399    }
400}
401impl miniserde::Deserialize for PriceBillingScheme {
402    fn begin(out: &mut Option<Self>) -> &mut dyn miniserde::de::Visitor {
403        crate::Place::new(out)
404    }
405}
406
407impl miniserde::de::Visitor for crate::Place<PriceBillingScheme> {
408    fn string(&mut self, s: &str) -> miniserde::Result<()> {
409        use std::str::FromStr;
410        self.out = Some(PriceBillingScheme::from_str(s).expect("infallible"));
411        Ok(())
412    }
413}
414
415stripe_types::impl_from_val_with_from_str!(PriceBillingScheme);
416#[cfg(feature = "deserialize")]
417impl<'de> serde::Deserialize<'de> for PriceBillingScheme {
418    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
419        use std::str::FromStr;
420        let s: std::borrow::Cow<'de, str> = serde::Deserialize::deserialize(deserializer)?;
421        Ok(Self::from_str(&s).expect("infallible"))
422    }
423}
424#[derive(Clone, Eq, PartialEq)]
425#[non_exhaustive]
426pub enum PriceTaxBehavior {
427    Exclusive,
428    Inclusive,
429    Unspecified,
430    /// An unrecognized value from Stripe. Should not be used as a request parameter.
431    Unknown(String),
432}
433impl PriceTaxBehavior {
434    pub fn as_str(&self) -> &str {
435        use PriceTaxBehavior::*;
436        match self {
437            Exclusive => "exclusive",
438            Inclusive => "inclusive",
439            Unspecified => "unspecified",
440            Unknown(v) => v,
441        }
442    }
443}
444
445impl std::str::FromStr for PriceTaxBehavior {
446    type Err = std::convert::Infallible;
447    fn from_str(s: &str) -> Result<Self, Self::Err> {
448        use PriceTaxBehavior::*;
449        match s {
450            "exclusive" => Ok(Exclusive),
451            "inclusive" => Ok(Inclusive),
452            "unspecified" => Ok(Unspecified),
453            v => {
454                tracing::warn!("Unknown value '{}' for enum '{}'", v, "PriceTaxBehavior");
455                Ok(Unknown(v.to_owned()))
456            }
457        }
458    }
459}
460impl std::fmt::Display for PriceTaxBehavior {
461    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
462        f.write_str(self.as_str())
463    }
464}
465
466impl std::fmt::Debug for PriceTaxBehavior {
467    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
468        f.write_str(self.as_str())
469    }
470}
471impl serde::Serialize for PriceTaxBehavior {
472    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
473    where
474        S: serde::Serializer,
475    {
476        serializer.serialize_str(self.as_str())
477    }
478}
479impl miniserde::Deserialize for PriceTaxBehavior {
480    fn begin(out: &mut Option<Self>) -> &mut dyn miniserde::de::Visitor {
481        crate::Place::new(out)
482    }
483}
484
485impl miniserde::de::Visitor for crate::Place<PriceTaxBehavior> {
486    fn string(&mut self, s: &str) -> miniserde::Result<()> {
487        use std::str::FromStr;
488        self.out = Some(PriceTaxBehavior::from_str(s).expect("infallible"));
489        Ok(())
490    }
491}
492
493stripe_types::impl_from_val_with_from_str!(PriceTaxBehavior);
494#[cfg(feature = "deserialize")]
495impl<'de> serde::Deserialize<'de> for PriceTaxBehavior {
496    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
497        use std::str::FromStr;
498        let s: std::borrow::Cow<'de, str> = serde::Deserialize::deserialize(deserializer)?;
499        Ok(Self::from_str(&s).expect("infallible"))
500    }
501}
502#[derive(Clone, Eq, PartialEq)]
503#[non_exhaustive]
504pub enum PriceTiersMode {
505    Graduated,
506    Volume,
507    /// An unrecognized value from Stripe. Should not be used as a request parameter.
508    Unknown(String),
509}
510impl PriceTiersMode {
511    pub fn as_str(&self) -> &str {
512        use PriceTiersMode::*;
513        match self {
514            Graduated => "graduated",
515            Volume => "volume",
516            Unknown(v) => v,
517        }
518    }
519}
520
521impl std::str::FromStr for PriceTiersMode {
522    type Err = std::convert::Infallible;
523    fn from_str(s: &str) -> Result<Self, Self::Err> {
524        use PriceTiersMode::*;
525        match s {
526            "graduated" => Ok(Graduated),
527            "volume" => Ok(Volume),
528            v => {
529                tracing::warn!("Unknown value '{}' for enum '{}'", v, "PriceTiersMode");
530                Ok(Unknown(v.to_owned()))
531            }
532        }
533    }
534}
535impl std::fmt::Display for PriceTiersMode {
536    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
537        f.write_str(self.as_str())
538    }
539}
540
541impl std::fmt::Debug for PriceTiersMode {
542    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
543        f.write_str(self.as_str())
544    }
545}
546impl serde::Serialize for PriceTiersMode {
547    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
548    where
549        S: serde::Serializer,
550    {
551        serializer.serialize_str(self.as_str())
552    }
553}
554impl miniserde::Deserialize for PriceTiersMode {
555    fn begin(out: &mut Option<Self>) -> &mut dyn miniserde::de::Visitor {
556        crate::Place::new(out)
557    }
558}
559
560impl miniserde::de::Visitor for crate::Place<PriceTiersMode> {
561    fn string(&mut self, s: &str) -> miniserde::Result<()> {
562        use std::str::FromStr;
563        self.out = Some(PriceTiersMode::from_str(s).expect("infallible"));
564        Ok(())
565    }
566}
567
568stripe_types::impl_from_val_with_from_str!(PriceTiersMode);
569#[cfg(feature = "deserialize")]
570impl<'de> serde::Deserialize<'de> for PriceTiersMode {
571    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
572        use std::str::FromStr;
573        let s: std::borrow::Cow<'de, str> = serde::Deserialize::deserialize(deserializer)?;
574        Ok(Self::from_str(&s).expect("infallible"))
575    }
576}
577#[derive(Clone, Eq, PartialEq)]
578#[non_exhaustive]
579pub enum PriceType {
580    OneTime,
581    Recurring,
582    /// An unrecognized value from Stripe. Should not be used as a request parameter.
583    Unknown(String),
584}
585impl PriceType {
586    pub fn as_str(&self) -> &str {
587        use PriceType::*;
588        match self {
589            OneTime => "one_time",
590            Recurring => "recurring",
591            Unknown(v) => v,
592        }
593    }
594}
595
596impl std::str::FromStr for PriceType {
597    type Err = std::convert::Infallible;
598    fn from_str(s: &str) -> Result<Self, Self::Err> {
599        use PriceType::*;
600        match s {
601            "one_time" => Ok(OneTime),
602            "recurring" => Ok(Recurring),
603            v => {
604                tracing::warn!("Unknown value '{}' for enum '{}'", v, "PriceType");
605                Ok(Unknown(v.to_owned()))
606            }
607        }
608    }
609}
610impl std::fmt::Display for PriceType {
611    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
612        f.write_str(self.as_str())
613    }
614}
615
616impl std::fmt::Debug for PriceType {
617    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
618        f.write_str(self.as_str())
619    }
620}
621impl serde::Serialize for PriceType {
622    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
623    where
624        S: serde::Serializer,
625    {
626        serializer.serialize_str(self.as_str())
627    }
628}
629impl miniserde::Deserialize for PriceType {
630    fn begin(out: &mut Option<Self>) -> &mut dyn miniserde::de::Visitor {
631        crate::Place::new(out)
632    }
633}
634
635impl miniserde::de::Visitor for crate::Place<PriceType> {
636    fn string(&mut self, s: &str) -> miniserde::Result<()> {
637        use std::str::FromStr;
638        self.out = Some(PriceType::from_str(s).expect("infallible"));
639        Ok(())
640    }
641}
642
643stripe_types::impl_from_val_with_from_str!(PriceType);
644#[cfg(feature = "deserialize")]
645impl<'de> serde::Deserialize<'de> for PriceType {
646    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
647        use std::str::FromStr;
648        let s: std::borrow::Cow<'de, str> = serde::Deserialize::deserialize(deserializer)?;
649        Ok(Self::from_str(&s).expect("infallible"))
650    }
651}