disneystreaming / smithy4s

https://disneystreaming.github.io/smithy4s/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Collection tags are ignored in DynamicSchemaIndex

kubukoz opened this issue · comments

//> using scala "3.4.1"
//> using dep "com.disneystreaming.smithy4s::smithy4s-json:0.18.15"
//> using dep "com.disneystreaming.smithy4s::smithy4s-dynamic:0.18.15"
import smithy4s.schema.Schema
import smithy4s.Blob
import smithy4s.json.Json
import smithy4s.ShapeId
import software.amazon.smithy.model.Model
import smithy4s.dynamic.DynamicSchemaIndex

val input =
  """
$version: "2"

namespace demo

structure Hello {
  @required name: String
}

@uniqueItems
list Hellos { member: Hello }
""".stripMargin

val dsi = DynamicSchemaIndex.loadModel(
  Model.assembler().addUnparsedModel("foo.smithy", input).assemble().unwrap()
)

val schema = dsi.getSchema(ShapeId.parse("demo#Hellos").get).get

println(schema.asInstanceOf[Schema.CollectionSchema[?, ?]].tag)

prints ListTag.

Is this intentional? It seems similar to how we (don't) handle refinements like @length, but it's inconsistent with how we do handle enum tags (including open enums).

Separate question, although one that follows from the above: if we were to capture collection tags as something more than hints, Dynamic will also fail to deconflict set items that are more complex than simple shapes - because of array equality (used for pretty much any aggregate shape in Dynamic). That pretty much makes Dynamic unfeasible without extra pre-processing before passing the schemas to standard codecs like Json / Document.

I don't think collection tags should be captured by Dynamic, as collection tags are performance related, not behaviour related. I think defaulting to lists is likely wrong, and defaulting to vectors may be better. Generally speaking, hints from smithy4s.meta should be disregarded by dynamic, if anything to save us some rabbit holes.

I do think our treatment of uniqueItems is off, as hinted in your other issue. It should be treated as a validation constraint, not as something dictating the collection type.

so the other issue (#1466 for other readers) would touch the general treatment of uniqueItems. I created #1469 (nice) for the vector default as per your suggestion.

I don't think we've addressed the array equality problem. If we consider uniqueItems similar to other constraint traits (which it may very well become after `#1469), it may make sense that we leave Dynamic out of it. However, if someone were to try and make Dynamic aware of such a constraint (for example, Playground does this for other constraints), how would they do that then? And I mean in existing codecs provided by smithy4s, not in custom schema compilers.

Exposing the "non-implicit, parameterized" refinements might help:

def patternConstraint[A](getValue: A => String): Simple[Pattern, A] =
new PatternConstraint[A](getValue)

but in this case I think you'd want sth like

def uniqueItemsRefinementProvider[A](mkEqualityCheck: Schema[A] => Eq[A]): Simple[UniqueItems, List[A], List[A]]

so that the equality check for a given type could be derived using, say, Document.Encoder. Does this sound reasonable?