Skip to content

Commit

Permalink
Fix refined newtypes (#1595)
Browse files Browse the repository at this point in the history
  • Loading branch information
kubukoz authored Oct 1, 2024
1 parent 85cf6a0 commit e5aa5b6
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Thank you!

# 0.18.25

* Fixes an issue in which refinements wouldn't work on custom simple shapes (newtypes) (see [#1595](https://github.com/disneystreaming/smithy4s/pull/1595))
* Fixes a regression from 0.18.4 which incorrectly rendered default values for certain types (see [#1593](https://github.com/disneystreaming/smithy4s/pull/1593))
* Fixes an issue in which union members targetting Unit would fail to compile when used as traits (see [#1600](https://github.com/disneystreaming/smithy4s/pull/1600)).
* Make the `transform` method in generated `*Gen` algebras final. This should make it possible to derive e.g. `FunctorK` instances in cats-tagless automatically (see [#1588](https://github.com/disneystreaming/smithy4s/pull/1588)).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package smithy4s.example

import smithy4s.Hints
import smithy4s.Schema
import smithy4s.ShapeId
import smithy4s.ShapeTag
import smithy4s.schema.Schema.struct

final case class HasConstrainedNewtype(s: CityId)

object HasConstrainedNewtype extends ShapeTag.Companion[HasConstrainedNewtype] {
val id: ShapeId = ShapeId("smithy4s.example", "HasConstrainedNewtype")

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(s: CityId): HasConstrainedNewtype = HasConstrainedNewtype(s)

implicit val schema: Schema[HasConstrainedNewtype] = struct(
CityId.schema.validated(smithy.api.Length(min = Some(1L), max = None)).required[HasConstrainedNewtype]("s", _.s),
)(make).withId(id).addHints(hints)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package smithy4s.example

import smithy4s.Hints
import smithy4s.Schema
import smithy4s.ShapeId
import smithy4s.ShapeTag
import smithy4s.schema.Schema.struct

final case class HasConstrainedNewtypes(a: BucketName, b: CityId, c: Option[ObjectSize] = None, d: Option[IndexedSeq[String]] = None, e: Option[PNG] = None)

object HasConstrainedNewtypes extends ShapeTag.Companion[HasConstrainedNewtypes] {
val id: ShapeId = ShapeId("smithy4s.example", "HasConstrainedNewtypes")

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(a: BucketName, b: CityId, c: Option[ObjectSize], d: Option[IndexedSeq[String]], e: Option[PNG]): HasConstrainedNewtypes = HasConstrainedNewtypes(a, b, c, d, e)

implicit val schema: Schema[HasConstrainedNewtypes] = struct(
BucketName.schema.validated(smithy.api.Length(min = Some(1L), max = None)).required[HasConstrainedNewtypes]("a", _.a),
CityId.schema.validated(smithy.api.Length(min = Some(1L), max = None)).required[HasConstrainedNewtypes]("b", _.b),
ObjectSize.schema.validated(smithy.api.Range(min = Some(scala.math.BigDecimal(1.0)), max = None)).optional[HasConstrainedNewtypes]("c", _.c),
SomeIndexSeq.underlyingSchema.validated(smithy.api.Length(min = Some(1L), max = None)).optional[HasConstrainedNewtypes]("d", _.d),
PNG.schema.validated(smithy.api.Length(min = Some(1L), max = None)).optional[HasConstrainedNewtypes]("e", _.e),
)(make).withId(id).addHints(hints)
}
9 changes: 7 additions & 2 deletions modules/core/src/smithy4s/RefinementProvider.scala
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,14 @@ private[smithy4s] trait LowPriorityImplicits {
: RefinementProvider[Pattern, E, E] =
new RefinementProvider.PatternConstraint[E](e => e.value)

implicit def isomorphismConstraint[C, A, A0](implicit
@deprecated("Use isomorphismConstraint2 instead", "0.18.25")
def isomorphismConstraint[C, A, A0](implicit
constraintOnA: RefinementProvider.Simple[C, A],
iso: Bijection[A, A0]
): RefinementProvider[C, A0, A0] = constraintOnA.imapFull[A0, A0](iso, iso)
): RefinementProvider[C, A0, A0] = isomorphismConstraint2

implicit def isomorphismConstraint2[C, A, A0](implicit
iso: Bijection[A, A0],
constraintOnA: RefinementProvider.Simple[C, A]
): RefinementProvider[C, A0, A0] = constraintOnA.imapFull[A0, A0](iso, iso)
}
20 changes: 20 additions & 0 deletions sampleSpecs/memberConstraints.smithy
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,23 @@ map ConstrainedMap {
value: String
}

// Regression test for https://github.com/disneystreaming/smithy4s/issues/1594
structure HasConstrainedNewtypes {
// string newtype
@length(min: 1)
@required
a: BucketName
// string newtype, double-constrained
@length(min: 1)
@required
b: CityId
// int newtype
@range(min: 1)
c: ObjectSize
// list newtype, oh wait these are just lists. Still.
@length(min: 1)
d: SomeIndexSeq
// blob newtype
@length(min: 1)
e: PNG
}

0 comments on commit e5aa5b6

Please sign in to comment.