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

feat: Add support for flexible defaults encoding #1652

Open
wants to merge 5 commits into
base: series/0.18
Choose a base branch
from

Conversation

ghostbuster91
Copy link
Contributor

@ghostbuster91 ghostbuster91 commented Feb 20, 2025

PR Checklist (not all items are relevant to all PRs)

  • Added unit-tests (for runtime code)
  • Added bootstrapped code + smoke tests (when the rendering logic is modified) N/A
  • Added build-plugins integration tests (when reflection loading is required at codegen-time) N/A
  • Added alloy compliance tests (when simpleRestJson protocol behaviour is expanded/updated) N/A
  • Updated dynamic module to match generated-code behaviour N/A
  • Added documentation
  • Updated changelog

Refers to #1398

Comment on lines +55 to +57
def compileOptional[A](
field: Field[?, A]
): FieldRenderPredicateCompiler.ShouldSkip[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.

thought: I was tempted to cast Field[?,A] to Field[?, Optional[A]] in OptionalPredicate but that doesn't work for fields with a default value.

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's call it SkipNonRequired instead. The term "optional" is more related to our Scala-specific interpretation, which differs to the absence of @required (for instance when default values are involve, as you point out)

wrappedCollection =>
wrappedCollection.asInstanceOf[Option[Any]].exists(predicate)
)
case LazySchema(_) => None // ?
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure what to do about that LazySchema. Should I simply write:

case LazySchema(inner) => asEmptyCollectionPredicate(inner.value)

?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think so. You'll have to add a test to ensure it doesn't recurse infinitely

wrappedCollection.asInstanceOf[Option[Any]].exists(predicate)
)
case LazySchema(_) => None // ?
case _: MapSchema[k, v] => None
Copy link
Contributor Author

Choose a reason for hiding this comment

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

question: should maps be also taken care of here?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes

import smithy4s.schema.Field
import smithy4s.schema.Schema

trait FieldRenderPredicateCompiler { self =>
Copy link
Contributor Author

@ghostbuster91 ghostbuster91 Feb 20, 2025

Choose a reason for hiding this comment

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

question: should this be sealed?

Copy link
Contributor

Choose a reason for hiding this comment

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

No, users should be able to create their own.

def this(cache: CompilationCache[DocumentEncoder]) =
this(cache, explicitDefaultsEncoding = false)

protected val explicitDefaultsEncoding: Boolean =
Copy link
Contributor Author

Choose a reason for hiding this comment

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

thought: kept for binary compatibility reasons

Copy link
Contributor

Choose a reason for hiding this comment

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

add a @deprecated onto it.

@ghostbuster91
Copy link
Contributor Author

I am not happy about the implementation of SkipIfEmptyCollection so I am fine with dropping it at this stage to minimize the amount of changes, but wanted to showcase it in case you think that it is worth to have something like that.

import smithy4s.schema.Field
import smithy4s.schema.Schema

trait FieldRenderPredicateCompiler { self =>
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's rename to FieldSkip

import smithy4s.schema.Schema

trait FieldRenderPredicateCompiler { self =>
def compile[A](
Copy link
Contributor

@Baccata Baccata Feb 21, 2025

Choose a reason for hiding this comment

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

let's change the interface to

def compile(label: String, schema: Schema[A]) : A => Boolean 

final def compileField[S, A](field: Field[S, A]) : A => Boolean  = compile(field.label, field.schema)

field: Field[?, A]
): FieldRenderPredicateCompiler.ShouldSkip[A]

def combine(
Copy link
Contributor

Choose a reason for hiding this comment

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

let's make two combinators : && and ||. The behaviour will be clearer to end-users


type ShouldSkip[A] = A => Boolean

trait OptionalPredicate extends FieldRenderPredicateCompiler {
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't make this public.

}

private def asEmptyCollectionPredicate[F[_]](
schema: Schema[_]
Copy link
Contributor

Choose a reason for hiding this comment

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

avoid using existential types as parameters : make it :

private def emptyCollectionPredicate[F[_], A](schema: Schema[A]) : Option[A => Boolean] 

val SkipIfEmptyOrDefaultOptionals =
SkipIfEmptyOptionals combine SkipIfDefaultOptionals

def fromExplicitDefaults(
Copy link
Contributor

Choose a reason for hiding this comment

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

remove this, just inline the code where it's used

}
}

val SkipIfEmptyOrDefaultOptionals =
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd rather we removed all the ones that are mere combinations, and let the users combine them themselves

@Baccata
Copy link
Contributor

Baccata commented Feb 21, 2025

A good start 👍

@ghostbuster91
Copy link
Contributor Author

@kubukoz wanna have a look?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants