-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UrlForm decoding support #1113
UrlForm decoding support #1113
Conversation
modules/core/src/smithy4s/http/internals/UrlFormDataDecoderSchemaVisitor.scala
Outdated
Show resolved
Hide resolved
modules/core/src/smithy4s/http/internals/UrlFormDataDecoderSchemaVisitor.scala
Outdated
Show resolved
Hide resolved
modules/core/src/smithy4s/http/internals/UrlFormDataEncoderSchemaVisitor.scala
Outdated
Show resolved
Hide resolved
This reads more easily and makes redundancy more obvious.
Same idea as the last commit, it makes reasoning about the operations that occur on the data easier.
It's not necessary.
Everything that this covered is now covered by UrlFormDataEncoderDecoderSchemaVisitorSpec.
There's not enough in common between that function and what OAuthCodecs does for lifting it out to have benefit.
PayloadCodec is used for Jsoniter based reading/writing because Jsonitor has a single trait for the read and write behaviour, and that's why PayloadCodec is used in those code paths. But for cases like this where reading and writing code paths are relatively separate, there's no benefit to combining them in a PayloadCodec.
It's not clear there is benefit to pushing string encoding into Blob. There probably isn't. The bug isn't something I've seen any impact from, I just noticed it while exploring the feasibility/benefit of handling the TODO.
project/Dependencies.scala
Outdated
@@ -29,7 +29,7 @@ object Dependencies { | |||
|
|||
val Alloy = new { | |||
val org = "com.disneystreaming.alloy" | |||
val alloyVersion = "0.2.5" | |||
val alloyVersion = "0.2.6" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This brings in urlFormFlattened
and urlFormName
from disneystreaming/alloy#110.
@@ -621,27 +607,20 @@ object XmlCodecSpec extends SimpleIOSuite { | |||
.map(result => expect.same(result, expected)) | |||
} | |||
|
|||
// Decode document differs from decode content in that the top-level | |||
// tag is checked against the ShapeId | |||
private def decodeDocument[A: Schema](document: XmlDocument): IO[A] = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't figure out why this was necessary. I believe I've been able to simplify things without losing anything, but might be worth a second opinion.
@@ -900,14 +900,14 @@ lazy val sandbox = projectMatrix | |||
// Ignore deprecation warnings here - it's all generated code, anyway. | |||
scalacOptions ++= Seq( | |||
"-Wconf:cat=deprecation:silent" | |||
) ++ scala3MigrationOption(scalaVersion.value), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't remember what this was doing now but I think it started causing a problem, and didn't seem to be necessary.
} | ||
object FormData { | ||
case object Empty extends FormData { | ||
final case class FormData(path: PayloadPath, maybeValue: Option[String]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Significant model simplification here. FormData
is no longer a coproduct. The various places that need to handle it can do so with less code that's also more readable.
val altMap = alternatives | ||
.map(altDecoder(_)) | ||
.toMap[PayloadPath.Segment, UrlFormDataDecoder[U]] | ||
({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
locally
is your friend. The parenthesis made me think this was a function application
.groupBy { case (index, _) => | ||
index | ||
} | ||
.toVector | ||
.sortBy { case (index, _) => | ||
index | ||
} | ||
.map { case (index, indicesAndValues) => | ||
UrlFormCursor( | ||
history, | ||
indicesAndValues.map { case (_, value) => value } | ||
) | ||
.down(PayloadPath.Segment.Index(index)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could use groupMap
to make it more efficient. It's available in 2.12 thanks to scala-collection-compat
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Done in e28d74d.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And for 2.12 in b0ad4eb.
.down(PayloadPath.Segment.Index(index)) | ||
} | ||
groupedAndSortedCursors | ||
.traverse[UrlFormDecodeError, A](memberDecoder.decode(_)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the toVector
is only there to satisfy the traverse, we can change/overload our traverse to accommodate the data structure and save an un-necessary .toVector
call
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is and it isn't. The result of groupBy
(and groupMap
) is a Map
, but we have to sort things before producing a result so that we're not making assumptions about input order. Map
isn't sortable. I did initially write toList
and puzzle over the compile error, before changing it to toVector
. So it's toVector
rather than toList
to satisfy the traverse, but not toVector
rather nothing to satisfy the traverse.
// be completely agnostic of AWS protocol details, they work with their | ||
// own more appropriately named hints - which is what necessitates the | ||
// translation here. | ||
Schema.transformHintsTransitivelyK { hints => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 (and thanks for the comment)
Good stuff overall, just a couple low-hanging fruits to address related to efficiency of list decoding |
Also remove unused ScalaCompat conversion and references.
@@ -28,9 +28,4 @@ private[smithy4s] trait ScalaCompat { | |||
private def opt[A](a: => A): Option[A] = try { Some(a) } | |||
catch { case scala.util.control.NonFatal(_) => None } | |||
} | |||
|
|||
private[smithy4s] implicit final class MapOps[K, V](val map: Map[K, V]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't see this being used anywhere.
@@ -16,8 +16,4 @@ | |||
|
|||
package smithy4s | |||
|
|||
private[smithy4s] trait ScalaCompat { | |||
implicit final class MapOps[K, V](val map: Map[K, V]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't see this being used anywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I merge the 2.13 and 3 ScalaCompat versions under src
?
@@ -16,8 +16,4 @@ | |||
|
|||
package smithy4s | |||
|
|||
private[smithy4s] trait ScalaCompat { | |||
implicit final class MapOps[K, V](val map: Map[K, V]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't see this being used anywhere.
@@ -30,8 +30,7 @@ import cats.kernel.Monoid | |||
|
|||
private[smithy4s] class XmlEncoderSchemaVisitor( | |||
val cache: CompilationCache[XmlEncoder] | |||
) extends SchemaVisitor.Cached[XmlEncoder] | |||
with smithy4s.ScalaCompat { compile => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work !
Follow up to #1120.
Related: disneystreaming/alloy#110
Changes:
UrlForm
model renaming TODOs.UrlForm
model by making encoder and decoder work with lists.Blob
and add regression test.urlFormFlattened
andurlFormName
from alloy so they're as AWS protocol agnostic as possible. AWS protocol codecs now translatexmlFlattened
tourlFormFlattened
andxmlName
tourlFormName
before passing schemas to the visitors.