@@ -60,7 +60,7 @@ private constructor(
6060 private val cropMode: JsonField <CropMode >,
6161 private val defaultImage: JsonField <String >,
6262 private val distort: JsonField <String >,
63- private val dpr: JsonField <Double >,
63+ private val dpr: JsonField <Dpr >,
6464 private val duration: JsonField <Duration >,
6565 private val endOffset: JsonField <EndOffset >,
6666 private val flip: JsonField <Flip >,
@@ -147,7 +147,7 @@ private constructor(
147147 @ExcludeMissing
148148 defaultImage: JsonField <String > = JsonMissing .of(),
149149 @JsonProperty(" distort" ) @ExcludeMissing distort: JsonField <String > = JsonMissing .of(),
150- @JsonProperty(" dpr" ) @ExcludeMissing dpr: JsonField <Double > = JsonMissing .of(),
150+ @JsonProperty(" dpr" ) @ExcludeMissing dpr: JsonField <Dpr > = JsonMissing .of(),
151151 @JsonProperty(" duration" ) @ExcludeMissing duration: JsonField <Duration > = JsonMissing .of(),
152152 @JsonProperty(" endOffset" )
153153 @ExcludeMissing
@@ -481,7 +481,7 @@ private constructor(
481481 * @throws ImageKitInvalidDataException if the JSON field has an unexpected type (e.g. if the
482482 * server responded with an unexpected value).
483483 */
484- fun dpr (): Optional <Double > = dpr.getOptional(" dpr" )
484+ fun dpr (): Optional <Dpr > = dpr.getOptional(" dpr" )
485485
486486 /* *
487487 * Specifies the duration (in seconds) for trimming videos, e.g., `5` or `10.5`. Typically used
@@ -994,7 +994,7 @@ private constructor(
994994 *
995995 * Unlike [dpr], this method doesn't throw if the JSON field has an unexpected type.
996996 */
997- @JsonProperty(" dpr" ) @ExcludeMissing fun _dpr (): JsonField <Double > = dpr
997+ @JsonProperty(" dpr" ) @ExcludeMissing fun _dpr (): JsonField <Dpr > = dpr
998998
999999 /* *
10001000 * Returns the raw JSON value of [duration].
@@ -1280,7 +1280,7 @@ private constructor(
12801280 private var cropMode: JsonField <CropMode > = JsonMissing .of()
12811281 private var defaultImage: JsonField <String > = JsonMissing .of()
12821282 private var distort: JsonField <String > = JsonMissing .of()
1283- private var dpr: JsonField <Double > = JsonMissing .of()
1283+ private var dpr: JsonField <Dpr > = JsonMissing .of()
12841284 private var duration: JsonField <Duration > = JsonMissing .of()
12851285 private var endOffset: JsonField <EndOffset > = JsonMissing .of()
12861286 private var flip: JsonField <Flip > = JsonMissing .of()
@@ -1752,15 +1752,21 @@ private constructor(
17521752 * [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations).
17531753 * - See [DPR](https://imagekit.io/docs/image-resize-and-crop#dpr---dpr).
17541754 */
1755- fun dpr (dpr : Double ) = dpr(JsonField .of(dpr))
1755+ fun dpr (dpr : Dpr ) = dpr(JsonField .of(dpr))
17561756
17571757 /* *
17581758 * Sets [Builder.dpr] to an arbitrary JSON value.
17591759 *
1760- * You should usually call [Builder.dpr] with a well-typed [Double ] value instead. This
1761- * method is primarily for setting the field to an undocumented or not yet supported value.
1760+ * You should usually call [Builder.dpr] with a well-typed [Dpr ] value instead. This method
1761+ * is primarily for setting the field to an undocumented or not yet supported value.
17621762 */
1763- fun dpr (dpr : JsonField <Double >) = apply { this .dpr = dpr }
1763+ fun dpr (dpr : JsonField <Dpr >) = apply { this .dpr = dpr }
1764+
1765+ /* * Alias for calling [dpr] with `Dpr.ofNumber(number)`. */
1766+ fun dpr (number : Double ) = dpr(Dpr .ofNumber(number))
1767+
1768+ /* * Alias for calling [dpr] with `Dpr.ofString(string)`. */
1769+ fun dpr (string : String ) = dpr(Dpr .ofString(string))
17641770
17651771 /* *
17661772 * Specifies the duration (in seconds) for trimming videos, e.g., `5` or `10.5`. Typically
@@ -2582,7 +2588,7 @@ private constructor(
25822588 cropMode().ifPresent { it.validate() }
25832589 defaultImage()
25842590 distort()
2585- dpr()
2591+ dpr().ifPresent { it.validate() }
25862592 duration().ifPresent { it.validate() }
25872593 endOffset().ifPresent { it.validate() }
25882594 flip().ifPresent { it.validate() }
@@ -2654,7 +2660,7 @@ private constructor(
26542660 (cropMode.asKnown().getOrNull()?.validity() ? : 0 ) +
26552661 (if (defaultImage.asKnown().isPresent) 1 else 0 ) +
26562662 (if (distort.asKnown().isPresent) 1 else 0 ) +
2657- (if ( dpr.asKnown().isPresent) 1 else 0 ) +
2663+ (dpr.asKnown().getOrNull()?.validity() ? : 0 ) +
26582664 (duration.asKnown().getOrNull()?.validity() ? : 0 ) +
26592665 (endOffset.asKnown().getOrNull()?.validity() ? : 0 ) +
26602666 (flip.asKnown().getOrNull()?.validity() ? : 0 ) +
@@ -4235,6 +4241,179 @@ private constructor(
42354241 override fun toString () = value.toString()
42364242 }
42374243
4244+ /* *
4245+ * Accepts values between 0.1 and 5, or `auto` for automatic device pixel ratio (DPR)
4246+ * calculation. Also accepts arithmetic expressions.
4247+ * - Learn about
4248+ * [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations).
4249+ * - See [DPR](https://imagekit.io/docs/image-resize-and-crop#dpr---dpr).
4250+ */
4251+ @JsonDeserialize(using = Dpr .Deserializer ::class )
4252+ @JsonSerialize(using = Dpr .Serializer ::class )
4253+ class Dpr
4254+ private constructor (
4255+ private val number: Double? = null ,
4256+ private val string: String? = null ,
4257+ private val _json : JsonValue ? = null ,
4258+ ) {
4259+
4260+ fun number (): Optional <Double > = Optional .ofNullable(number)
4261+
4262+ fun string (): Optional <String > = Optional .ofNullable(string)
4263+
4264+ fun isNumber (): Boolean = number != null
4265+
4266+ fun isString (): Boolean = string != null
4267+
4268+ fun asNumber (): Double = number.getOrThrow(" number" )
4269+
4270+ fun asString (): String = string.getOrThrow(" string" )
4271+
4272+ fun _json (): Optional <JsonValue > = Optional .ofNullable(_json )
4273+
4274+ fun <T > accept (visitor : Visitor <T >): T =
4275+ when {
4276+ number != null -> visitor.visitNumber(number)
4277+ string != null -> visitor.visitString(string)
4278+ else -> visitor.unknown(_json )
4279+ }
4280+
4281+ private var validated: Boolean = false
4282+
4283+ fun validate (): Dpr = apply {
4284+ if (validated) {
4285+ return @apply
4286+ }
4287+
4288+ accept(
4289+ object : Visitor <Unit > {
4290+ override fun visitNumber (number : Double ) {}
4291+
4292+ override fun visitString (string : String ) {}
4293+ }
4294+ )
4295+ validated = true
4296+ }
4297+
4298+ fun isValid (): Boolean =
4299+ try {
4300+ validate()
4301+ true
4302+ } catch (e: ImageKitInvalidDataException ) {
4303+ false
4304+ }
4305+
4306+ /* *
4307+ * Returns a score indicating how many valid values are contained in this object
4308+ * recursively.
4309+ *
4310+ * Used for best match union deserialization.
4311+ */
4312+ @JvmSynthetic
4313+ internal fun validity (): Int =
4314+ accept(
4315+ object : Visitor <Int > {
4316+ override fun visitNumber (number : Double ) = 1
4317+
4318+ override fun visitString (string : String ) = 1
4319+
4320+ override fun unknown (json : JsonValue ? ) = 0
4321+ }
4322+ )
4323+
4324+ override fun equals (other : Any? ): Boolean {
4325+ if (this == = other) {
4326+ return true
4327+ }
4328+
4329+ return other is Dpr && number == other.number && string == other.string
4330+ }
4331+
4332+ override fun hashCode (): Int = Objects .hash(number, string)
4333+
4334+ override fun toString (): String =
4335+ when {
4336+ number != null -> " Dpr{number=$number }"
4337+ string != null -> " Dpr{string=$string }"
4338+ _json != null -> " Dpr{_unknown=$_json }"
4339+ else -> throw IllegalStateException (" Invalid Dpr" )
4340+ }
4341+
4342+ companion object {
4343+
4344+ @JvmStatic fun ofNumber (number : Double ) = Dpr (number = number)
4345+
4346+ @JvmStatic fun ofString (string : String ) = Dpr (string = string)
4347+ }
4348+
4349+ /* * An interface that defines how to map each variant of [Dpr] to a value of type [T]. */
4350+ interface Visitor <out T > {
4351+
4352+ fun visitNumber (number : Double ): T
4353+
4354+ fun visitString (string : String ): T
4355+
4356+ /* *
4357+ * Maps an unknown variant of [Dpr] to a value of type [T].
4358+ *
4359+ * An instance of [Dpr] can contain an unknown variant if it was deserialized from data
4360+ * that doesn't match any known variant. For example, if the SDK is on an older version
4361+ * than the API, then the API may respond with new variants that the SDK is unaware of.
4362+ *
4363+ * @throws ImageKitInvalidDataException in the default implementation.
4364+ */
4365+ fun unknown (json : JsonValue ? ): T {
4366+ throw ImageKitInvalidDataException (" Unknown Dpr: $json " )
4367+ }
4368+ }
4369+
4370+ internal class Deserializer : BaseDeserializer <Dpr >(Dpr : :class) {
4371+
4372+ override fun ObjectCodec.deserialize (node : JsonNode ): Dpr {
4373+ val json = JsonValue .fromJsonNode(node)
4374+
4375+ val bestMatches =
4376+ sequenceOf(
4377+ tryDeserialize(node, jacksonTypeRef<String >())?.let {
4378+ Dpr (string = it, _json = json)
4379+ },
4380+ tryDeserialize(node, jacksonTypeRef<Double >())?.let {
4381+ Dpr (number = it, _json = json)
4382+ },
4383+ )
4384+ .filterNotNull()
4385+ .allMaxBy { it.validity() }
4386+ .toList()
4387+ return when (bestMatches.size) {
4388+ // This can happen if what we're deserializing is completely incompatible with
4389+ // all the possible variants (e.g. deserializing from boolean).
4390+ 0 -> Dpr (_json = json)
4391+ 1 -> bestMatches.single()
4392+ // If there's more than one match with the highest validity, then use the first
4393+ // completely valid match, or simply the first match if none are completely
4394+ // valid.
4395+ else -> bestMatches.firstOrNull { it.isValid() } ? : bestMatches.first()
4396+ }
4397+ }
4398+ }
4399+
4400+ internal class Serializer : BaseSerializer <Dpr >(Dpr : :class) {
4401+
4402+ override fun serialize (
4403+ value : Dpr ,
4404+ generator : JsonGenerator ,
4405+ provider : SerializerProvider ,
4406+ ) {
4407+ when {
4408+ value.number != null -> generator.writeObject(value.number)
4409+ value.string != null -> generator.writeObject(value.string)
4410+ value._json != null -> generator.writeObject(value._json )
4411+ else -> throw IllegalStateException (" Invalid Dpr" )
4412+ }
4413+ }
4414+ }
4415+ }
4416+
42384417 /* *
42394418 * Specifies the duration (in seconds) for trimming videos, e.g., `5` or `10.5`. Typically used
42404419 * with startOffset to indicate the length from the start offset. Arithmetic expressions are
0 commit comments