Skip to content

Commit

Permalink
List<T> -> Option<List<T>>, no more List<T> defaults
Browse files Browse the repository at this point in the history
  • Loading branch information
mzeitlin11 committed Dec 23, 2023
1 parent 3abe2e6 commit d8a2dec
Show file tree
Hide file tree
Showing 19 changed files with 34 additions and 63 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ should include the dependency `stripe_webhook` and import from that crate instea
- `Deleted<>` objects (such `Deleted<Account>`) no longer expose a boolean `deleted`. This was always `true` and only
used internally as a discriminant when deserializing. The generic type `Deleted` has been removed and replaced by
generated types such as `DeletedAccount`, which sometimes contain additional fields.
- Optional `List<T>` no longer deserialized with `serde(default)`, the type has been changed `List<T>` -> `Option<List<T>>`. The default
implementation of `List<T>` produced data not upholding the `List<T>` invariant of having a meaningful `url`.
- Types used only for requests now use borrowed types more consistently (and more often). For example, previously the top-level
`CreateCustomer.description` expected `Option<&str>`, but `CreateCustomerShipping.phone` expected `Option<String>`. Now
both expect `Option<&str>`. In general, the following changes are made to request parameters that required owned data:
Expand Down
7 changes: 4 additions & 3 deletions examples/endpoints/src/checkout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,17 @@ pub async fn run_checkout_session_example(client: &stripe::Client) -> Result<(),
params.send(client).await?
};

let created_item = &checkout_session.line_items.expect("line items were created").data[0];
println!(
"created a {} checkout session for {} {:?} for {} {} at {}",
checkout_session.payment_status,
checkout_session.line_items.data[0].quantity.unwrap(),
match &checkout_session.line_items.data[0].price.as_ref().unwrap().product {
created_item.quantity.unwrap(),
match &created_item.price.as_ref().unwrap().product {
Expandable::Object(p) => &p.name,
_ => panic!("product not found"),
},
checkout_session.amount_subtotal.unwrap() / 100,
checkout_session.line_items.data[0].price.as_ref().unwrap().currency,
created_item.price.as_ref().unwrap().currency,
checkout_session.url.unwrap()
);
Ok(())
Expand Down
4 changes: 2 additions & 2 deletions generated/stripe_checkout/src/checkout_session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ pub struct CheckoutSession {
/// Details on the state of invoice creation for the Checkout Session.
pub invoice_creation: Option<stripe_checkout::PaymentPagesCheckoutSessionInvoiceCreation>,
/// The line items purchased by the customer.
#[serde(default)]
pub line_items: stripe_types::List<stripe_shared::CheckoutSessionItem>,
#[serde(skip_serializing_if = "Option::is_none")]
pub line_items: Option<stripe_types::List<stripe_shared::CheckoutSessionItem>>,
/// Has the value `true` if the object exists in live mode or the value `false` if the object exists in test mode.
pub livemode: bool,
/// The IETF language tag of the locale Checkout is displayed in.
Expand Down
2 changes: 1 addition & 1 deletion generated/stripe_misc/src/tax_calculation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct TaxCalculation {
/// Unique identifier for the calculation.
pub id: Option<stripe_misc::tax_calculation::TaxCalculationId>,
/// The list of items the customer is purchasing.
pub line_items: stripe_types::List<stripe_misc::TaxCalculationLineItem>,
pub line_items: Option<stripe_types::List<stripe_misc::TaxCalculationLineItem>>,
/// Has the value `true` if the object exists in live mode or the value `false` if the object exists in test mode.
pub livemode: bool,
/// The shipping cost details for the calculation.
Expand Down
2 changes: 1 addition & 1 deletion generated/stripe_misc/src/tax_transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct TaxTransaction {
/// Unique identifier for the transaction.
pub id: stripe_misc::tax_transaction::TaxTransactionId,
/// The tax collected or refunded, by line item.
pub line_items: stripe_types::List<stripe_misc::TaxTransactionLineItem>,
pub line_items: Option<stripe_types::List<stripe_misc::TaxTransactionLineItem>>,
/// Has the value `true` if the object exists in live mode or the value `false` if the object exists in test mode.
pub livemode: bool,
/// Set of [key-value pairs](https://stripe.com/docs/api/metadata) that you can attach to an object.
Expand Down
4 changes: 2 additions & 2 deletions generated/stripe_shared/src/account/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ pub struct Account {
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<String>,
/// External accounts (bank accounts and debit cards) currently attached to this account.
#[serde(default)]
pub external_accounts: stripe_types::List<stripe_shared::ExternalAccount>,
#[serde(skip_serializing_if = "Option::is_none")]
pub external_accounts: Option<stripe_types::List<stripe_shared::ExternalAccount>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub future_requirements: Option<stripe_shared::AccountFutureRequirements>,
/// Unique identifier for the object.
Expand Down
2 changes: 1 addition & 1 deletion generated/stripe_shared/src/charge/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ pub struct Charge {
/// If the charge is only partially refunded, this attribute will still be false.
pub refunded: bool,
/// A list of refunds that have been applied to the charge.
pub refunds: stripe_types::List<stripe_shared::Refund>,
pub refunds: Option<stripe_types::List<stripe_shared::Refund>>,
/// ID of the review associated with this charge if one exists.
pub review: Option<stripe_types::Expandable<stripe_shared::Review>>,
/// Shipping information for the charge.
Expand Down
12 changes: 6 additions & 6 deletions generated/stripe_shared/src/customer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ pub struct Customer {
/// Appears on invoices emailed to this customer.
pub shipping: Option<stripe_shared::Shipping>,
/// The customer's payment sources, if any.
#[serde(default)]
pub sources: stripe_types::List<stripe_shared::PaymentSource>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sources: Option<stripe_types::List<stripe_shared::PaymentSource>>,
/// The customer's current subscriptions, if any.
#[serde(default)]
pub subscriptions: stripe_types::List<stripe_shared::Subscription>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subscriptions: Option<stripe_types::List<stripe_shared::Subscription>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tax: Option<stripe_shared::CustomerTax>,
/// Describes the customer's tax exemption status, which is `none`, `exempt`, or `reverse`.
Expand All @@ -101,8 +101,8 @@ pub struct Customer {
#[serde(skip_serializing_if = "Option::is_none")]
pub tax_exempt: Option<CustomerTaxExempt>,
/// The customer's tax IDs.
#[serde(default)]
pub tax_ids: stripe_types::List<stripe_shared::TaxId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tax_ids: Option<stripe_types::List<stripe_shared::TaxId>>,
/// ID of the test clock that this customer belongs to.
#[serde(skip_serializing_if = "Option::is_none")]
pub test_clock: Option<stripe_types::Expandable<stripe_shared::TestHelpersTestClock>>,
Expand Down
4 changes: 2 additions & 2 deletions generated/stripe_shared/src/file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ pub struct File {
/// Unique identifier for the object.
pub id: stripe_shared::file::FileId,
/// A list of [file links](https://stripe.com/docs/api#file_links) that point at this file.
#[serde(default)]
pub links: stripe_types::List<stripe_shared::FileLink>,
#[serde(skip_serializing_if = "Option::is_none")]
pub links: Option<stripe_types::List<stripe_shared::FileLink>>,
/// The [purpose](https://stripe.com/docs/file-upload#uploading-a-file) of the uploaded file.
pub purpose: FilePurpose,
/// The size of the file object in bytes.
Expand Down
4 changes: 2 additions & 2 deletions generated/stripe_shared/src/payment_link/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ pub struct PaymentLink {
/// Configuration for creating invoice for payment mode payment links.
pub invoice_creation: Option<stripe_shared::PaymentLinksResourceInvoiceCreation>,
/// The line items representing what is being sold.
#[serde(default)]
pub line_items: stripe_types::List<stripe_shared::CheckoutSessionItem>,
#[serde(skip_serializing_if = "Option::is_none")]
pub line_items: Option<stripe_types::List<stripe_shared::CheckoutSessionItem>>,
/// Has the value `true` if the object exists in live mode or the value `false` if the object exists in test mode.
pub livemode: bool,
/// Set of [key-value pairs](https://stripe.com/docs/api/metadata) that you can attach to an object.
Expand Down
4 changes: 2 additions & 2 deletions generated/stripe_shared/src/quote/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ pub struct Quote {
/// All invoices will be billed using the specified settings.
pub invoice_settings: Option<stripe_shared::InvoiceSettingQuoteSetting>,
/// A list of items the customer is being quoted for.
#[serde(default)]
pub line_items: stripe_types::List<stripe_shared::CheckoutSessionItem>,
#[serde(skip_serializing_if = "Option::is_none")]
pub line_items: Option<stripe_types::List<stripe_shared::CheckoutSessionItem>>,
/// Has the value `true` if the object exists in live mode or the value `false` if the object exists in test mode.
pub livemode: bool,
/// Set of [key-value pairs](https://stripe.com/docs/api/metadata) that you can attach to an object.
Expand Down
4 changes: 2 additions & 2 deletions generated/stripe_shared/src/quotes_resource_upfront/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub struct QuotesResourceUpfront {
/// The line items that will appear on the next invoice after this quote is accepted.
///
/// This does not include pending invoice items that exist on the customer but may still be included in the next invoice.
#[serde(default)]
pub line_items: stripe_types::List<stripe_shared::CheckoutSessionItem>,
#[serde(skip_serializing_if = "Option::is_none")]
pub line_items: Option<stripe_types::List<stripe_shared::CheckoutSessionItem>>,
pub total_details: stripe_shared::QuotesResourceTotalDetails,
}
2 changes: 1 addition & 1 deletion generated/stripe_treasury/src/treasury_transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct TreasuryTransaction {
/// A list of TransactionEntries that are part of this Transaction.
///
/// This cannot be expanded in any list endpoints.
pub entries: stripe_types::List<stripe_treasury::TreasuryTransactionEntry>,
pub entries: Option<stripe_types::List<stripe_treasury::TreasuryTransactionEntry>>,
/// The FinancialAccount associated with this object.
pub financial_account: String,
/// ID of the flow that created the Transaction.
Expand Down
17 changes: 0 additions & 17 deletions openapi/src/rust_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,23 +221,6 @@ impl StructField {
}
}

/// Specifications for a `serde(default = ...)` attribute
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default, Hash)]
pub enum DeserDefault {
/// Just `serde(default)`
#[default]
Default,
}

impl DeserDefault {
/// The corresponding `serde` attribute
pub fn to_serde_attr(self) -> &'static str {
match self {
Self::Default => "#[serde(default)]",
}
}
}

pub struct ObjectRef {
pub path: ComponentPath,
pub feature_gate: Option<String>,
Expand Down
13 changes: 2 additions & 11 deletions openapi/src/rust_type.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt::{Debug, Display, Formatter};

use crate::components::Components;
use crate::rust_object::{DeserDefault, ObjectMetadata, RustObject};
use crate::rust_object::{ObjectMetadata, RustObject};
use crate::types::{ComponentPath, RustIdent};
use crate::visitor::{Visit, VisitMut};

Expand Down Expand Up @@ -202,7 +202,7 @@ impl RustType {

pub fn into_nullable(self) -> Self {
match self {
Self::Container(Container::List(_)) | Self::Container(Container::Option(_)) => self,
Self::Container(Container::Option(_)) => self,
_ => Self::option(self),
}
}
Expand Down Expand Up @@ -248,15 +248,6 @@ impl RustType {
self.as_object().map(|r| r.0)
}

pub fn deser_default(&self) -> Option<DeserDefault> {
match self {
Self::Simple(SimpleType::Bool)
| Self::Container(Container::Vec(_))
| Self::Container(Container::List(_)) => Some(DeserDefault::Default),
_ => None,
}
}

pub fn visit<'a, T: Visit<'a>>(&'a self, visitor: &mut T) {
use RustType::*;
match self {
Expand Down
3 changes: 0 additions & 3 deletions openapi/src/templates/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,6 @@ impl<'a> ObjectWriter<'a> {
if let Some(skip_ser) = field.rust_type.skip_serializing() {
let _ = writeln!(out, r#"#[serde(skip_serializing_if = "{skip_ser}")]"#);
}
if let Some(default) = field.rust_type.deser_default() {
let _ = writeln!(out, "{}", default.to_serde_attr());
}
}

let printable = self.get_printable(&field.rust_type);
Expand Down
6 changes: 0 additions & 6 deletions stripe_types/src/pagination.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,6 @@ pub struct List<T> {
pub url: String,
}

impl<T> Default for List<T> {
fn default() -> Self {
List { data: Vec::new(), has_more: false, total_count: None, url: String::new() }
}
}

impl<T: Clone> Clone for List<T> {
fn clone(&self) -> Self {
List {
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/it/blocking/charge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ fn is_charge_retrievable() {
assert_eq!(charge.id, "ch_123");
assert!(charge.customer.is_none());
assert!(charge.invoice.is_none());
assert_eq!(charge.refunds.data.len(), 1);
assert_eq!(charge.refunds.unwrap().data.len(), 1);
});
}
3 changes: 3 additions & 0 deletions tests/tests/it/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ mod price;
mod async_tests;
#[cfg(feature = "blocking")]
mod blocking;
// NB: pagination utils ideally could be used for blocking tests as well, but tricky because the `MockServer` is async
// and the blocking client unconditionally creates its own runtime already
#[cfg(feature = "async")]
mod pagination_utils;

0 comments on commit d8a2dec

Please sign in to comment.