Skip to content
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

add hint mask construct #70

Merged
merged 26 commits into from
Jan 26, 2022
Merged

add hint mask construct #70

merged 26 commits into from
Jan 26, 2022

Conversation

lewisjkl
Copy link
Contributor

@lewisjkl lewisjkl commented Jan 21, 2022

Introduces the concept of HintMask that is derived from smithy protocolDefinitions

Comment on lines 22 to 24
smithy4s.http.json.codecs(
HintMask()
) // TODO smithy4s.api.SimpleRestJson.hintMask??
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great it we could apply the hint mask across the codecs from the SimpleProtocolBuilder rather than needing to do it everywhere. The issue I had with doing this was that the SimpleProtocolBuilder does not have direct access to the schematic (it works with the CodecAPI).

My initial thought here was that we could codegen the hintMask for protocols as part of the rendering. Not sure if there is a better way. The current protocols only have a list of TraitShapeId like: smithy.api.ProtocolDefinition(Some(List(smithy.api.TraitShapeId("smithy.api#cors"), .... I tried looking at the renderer, but couldn't confidently figure out how to begin approaching this 😅

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great it we could apply the hint mask across the codecs from the SimpleProtocolBuilder

We could add a method to the CodecAPI interface tbh.

I tried looking at the renderer, but couldn't confidently figure out how to begin approaching this

that's cool, we'll have a brainstorm next week, but the progress at this point in time is already very satisfying.

Comment on lines 17 to 32
@protocolDefinition(traits: [
"smithy.api#cors",
"smithy.api#endpoint",
"smithy.api#hostLabel",
"smithy.api#http",
"smithy.api#httpError",
"smithy.api#httpHeader",
"smithy.api#httpLabel",
"smithy.api#httpPayload",
"smithy.api#httpPrefixHeaders",
"smithy.api#httpQuery",
"smithy.api#httpQueryParams",
"smithy.api#httpResponseCode",
"smithy.api#jsonName",
"smithy.api#timestampFormat"
])
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are all just copied from the aws restJson1 protocol. Some of them may not apply here and we have a few others that need to be added (e.g. discriminated)

modules/core/src/smithy4s/HintMask.scala Outdated Show resolved Hide resolved
@@ -113,4 +113,8 @@ package object syntax
OneOf(oneOf.label, oneOf.schema.withHints(hints: _*), oneOf.inject)
}

implicit class withMaskSyntax[F[_]](val s: Schematic[F]) extends AnyVal {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s should be private, otherwise you can do schematic.s.s.s.s.s I think

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm not sure it should leave there tbh, nor that it should be a extension, but 🤷

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, I think it has proved less useful than I thought it would initially anyway

@@ -14,7 +14,22 @@ namespace smithy4s.api
@uuidFormat
string UUID

@protocolDefinition
@protocolDefinition(traits: [
"smithy.api#cors",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does @discriminated belong here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also @ error, if it's a thing (can't remember, on phone, just spitballing)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't see the previous comments when I was writing this :D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries :) appreciate the comments!

"smithy.api#httpHeader",
"smithy.api#httpLabel",
"smithy.api#httpPayload",
"smithy.api#httpPrefixHeaders",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gotta learn what this is :D

modules/json/src/smithy4s/http/json/codecs.scala Outdated Show resolved Hide resolved
abstract class HintMask {
protected def toSet: Set[Hints.Key[_]]
def ++(other: HintMask): HintMask
def apply(hints: Hints): Hints
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice :)

private[this] final class MaskSchematic[F[_]](
schematic: Schematic[F],
mask: HintMask
) extends PassthroughSchematic[F](schematic) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea !

mask: HintMask
) extends PassthroughSchematic[F](schematic) {
override def withHints[A](fa: F[A], hints: Hints): F[A] =
schematic.withHints(fa, mask(hints))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


class PassthroughSchematic[F[_]](schematic: Schematic[F])
extends Schematic[F]
with GenericAritySchematic[F] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So unfortunately, this Passthrough construct should not extend this. We'll have to use the build-time Boilerplate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that because the schematics passed in may not be using the generic arity trait so they would rely on the other functions directly?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes indeed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could just delete the non-generic arity methods in the schematic interface. I think experience shows that we always use the generic one anyway.

We would however keep the arity-based methods in the syntax package, to create schemas. They would just all delegate to the generic-arity one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I am fine with that. I just implemented them all in case we decide to go that route.. I agree though that the generic route seems to be sufficient.

def mask(hintMask: HintMask): Schematic[F] = HintMask.mask(s, hintMask)
}

implicit def newTypeToHintKey[A](a: Newtype[A]): Hints.Key[_] = a.key
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if you return Hints.Key[A] here ? Does the generated code still compile ? If it does, we should do that, and maybe move this implicit def into the companion object of Hints.Key

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I will give that a try

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't compile like that:

type mismatch;
 found   : smithy4s.Hints.Key[a.Type]
 required: smithy4s.Hints.Key[A]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to the companion object though as I think that is better

if (
hints.contains(Hint.ClientError) || hints.contains(Hint.ServerError)
) {
if (hints.contains(Hint.Error)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -40,7 +40,7 @@ trait CodecAPI {
* @param schema the value's schema
* @return the codec associated to the A value.
*/
def compileCodec[A](schema: Schema[A]): Codec[A]
def compileCodec[A](schema: Schema[A], hintMask: HintMask): Codec[A]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like this, the application of the hintMask should be an implementation detail of the CodecAPI instances I think

@lewisjkl lewisjkl marked this pull request as ready for review January 25, 2022 20:55
object SimpleRestJsonBuilder
extends SimpleProtocolBuilder[smithy4s.api.SimpleRestJson](
smithy4s.http.json.codecs
smithy4s.http.json.codecs(
smithy4s.api.SimpleRestJson.protocol.hintMask ++ HintMask(InputOutput)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick (if-minor): Kind of makes me think the standard hints (smithy.api) should always be forwarded no matter what.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah : imagine you want to have a json RPC API and also serve it over http/restJson. You need a mechanism to ignore the http binding traits when using the RPC protocol (or re-implement a bespoke schematic)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like smithy.api is too generic a package then 😅

@kubukoz kubukoz merged commit 03a60cb into main Jan 26, 2022
@kubukoz kubukoz deleted the hint-masks branch January 26, 2022 19:58
Baccata added a commit that referenced this pull request May 10, 2022
Co-authored-by: Olivier Mélois <baccata64@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants