See also #1658.
This updates the behavior of `CustomerInfoResponse` decoding so that having invalid content inside of one of the structures fails more loudly instead of getting ignored.
For that, `@DefaultValue` no longer ignores errors, and instead `@IgnoreDecodeErrors` must be used.
For some of the values in `CustomerInfoResponse` this makes sense (like `Store`), but not for things like subscriptions where we would be losing data.
The method doesn't actually throw, so calling `throw decoder.throwValueNotFoundError()` was confusing. Now the code reads `throw decoder.valueNotFoundError()`.
This allows having properties in an `Encodable` type that won't be encoded.
This will be used to storing the `rawData` when decoding our types (see #1496).
A future PR will make use of these: #1540.
The purpose of this is to be able to define `Decodable` types with default values without needing to implement the whole `init(from decoder: Decoder)` from scratch. If any one property has a default value, that's the only way to provide it without these.
For example, `EntitlementInfo.ProductData` implements this:
```swift
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.isSandbox = try container.decodeIfPresent(Bool.self, forKey: .isSandbox) ?? false
self.originalPurchaseDate = try container.decodeIfPresent(Date.self, forKey: .originalPurchaseDate)
self.expiresDate = try container.decodeIfPresent(Date.self, forKey: .expiresDate)
self.unsubscribeDetectedAt = try container.decodeIfPresent(Date.self, forKey: .unsubscribeDetectedAt)
self.billingIssuesDetectedAt = try container.decodeIfPresent(Date.self, forKey: .billingIssuesDetectedAt)
self.periodType = container.decode(PeriodType.self, forKey: .periodType, defaultValue: .normal)
self.store = container.decode(Store.self, forKey: .store, defaultValue: .unknownStore)
self.ownershipType = container.decode(PurchaseOwnershipType.self,
forKey: .ownershipType,
defaultValue: .purchased)
}
```
With these new types, that whole implementation is unnecessary and can be data-driven instead, which is more maintanable and less error-prone:
```swift
struct ProductData: Decodable {
@DefaultValue<PeriodType> var periodType: PeriodType
var originalPurchaseDate: Date?
var expiresDate: Date?
@DefaultValue<Store> var store: Store
@DefaultDecodable.False var isSandbox: Bool
var unsubscribeDetectedAt: Date?
var billingIssuesDetectedAt: Date?
@DefaultValue<PurchaseOwnershipType> var ownershipType: PurchaseOwnershipType
}
```