All Downloads are FREE. Search and download functionalities are using the official Maven repository.

smithy4s.schema.SchemaVisitor.scala Maven / Gradle / Ivy

There is a newer version: 0.19.0-41-91762fb
Show newest version
/*
 *  Copyright 2021-2024 Disney Streaming
 *
 *  Licensed under the Tomorrow Open Source Technology License, Version 1.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     https://disneystreaming.github.io/TOST-1.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package smithy4s
package schema

import Schema._
import smithy4s.kinds.OptionK

// format: off
trait SchemaVisitor[F[_]] extends (Schema ~> F) { self =>
  def primitive[P](shapeId: ShapeId, hints: Hints, tag: Primitive[P]): F[P]
  def collection[C[_], A](shapeId: ShapeId, hints: Hints, tag: CollectionTag[C], member: Schema[A]): F[C[A]]
  def map[K, V](shapeId: ShapeId, hints: Hints, key: Schema[K], value: Schema[V]): F[Map[K, V]]
  def enumeration[E](shapeId: ShapeId, hints: Hints, tag: EnumTag[E], values: List[EnumValue[E]], total: E => EnumValue[E]): F[E]
  def struct[S](shapeId: ShapeId, hints: Hints, fields: Vector[Field[S, _]], make: IndexedSeq[Any] => S): F[S]
  def union[U](shapeId: ShapeId, hints: Hints, alternatives: Vector[Alt[U, _]], dispatch: Alt.Dispatcher[U]): F[U]
  def biject[A, B](schema: Schema[A], bijection: Bijection[A, B]): F[B]
  def refine[A, B](schema: Schema[A], refinement: Refinement[A, B]): F[B]
  def lazily[A](suspend: Lazy[Schema[A]]): F[A]
  def option[A](schema: Schema[A]): F[Option[A]]

  def apply[A](schema: Schema[A]): F[A] = schema match {
    case PrimitiveSchema(shapeId, hints, tag) => primitive(shapeId, hints, tag)
    case s: CollectionSchema[c, a] => collection[c,a](s.shapeId, s.hints, s.tag, s.member)
    case MapSchema(shapeId, hints, key, value) => map(shapeId, hints, key, value)
    case EnumerationSchema(shapeId, hints, tag, values, total) => enumeration(shapeId, hints, tag, values, total)
    case StructSchema(shapeId, hints, fields, make) => struct(shapeId, hints, fields, make)
    case u@UnionSchema(shapeId, hints, alts, _) => union(shapeId, hints, alts, Alt.Dispatcher.fromUnion(u))
    case BijectionSchema(schema, bijection) => biject(schema, bijection)
    case RefinementSchema(schema, refinement) => refine(schema, refinement)
    case LazySchema(make) => lazily(make)
    case OptionSchema(a) => option(a)
  }

}



object SchemaVisitor { outer =>

  trait Default[F[_]] extends SchemaVisitor[F]{
    def default[A]: F[A]
    override def primitive[P](shapeId: ShapeId, hints: Hints, tag: Primitive[P]): F[P] = default
    override def collection[C[_], A](shapeId: ShapeId, hints: Hints, tag: CollectionTag[C], member: Schema[A]): F[C[A]] = default
    override def map[K, V](shapeId: ShapeId, hints: Hints, key: Schema[K], value: Schema[V]): F[Map[K,V]] = default
    override def enumeration[E](shapeId: ShapeId, hints: Hints, tag: EnumTag[E], values: List[EnumValue[E]], total: E => EnumValue[E]): F[E] = default
    override def struct[S](shapeId: ShapeId, hints: Hints, fields: Vector[Field[S, _]], make: IndexedSeq[Any] => S): F[S] = default
    override def union[U](shapeId: ShapeId, hints: Hints, alternatives: Vector[Alt[U, _]], dispatch: Alt.Dispatcher[U]): F[U] = default
    override def biject[A, B](schema: Schema[A], bijection: Bijection[A, B]): F[B] = default
    override def refine[A, B](schema: Schema[A], refinement: Refinement[A, B]): F[B] = default
    override def lazily[A](suspend: Lazy[Schema[A]]): F[A] = default
    override def option[A](schema: Schema[A]): F[Option[A]] = default
  }

  trait Optional[F[_]] extends Default[OptionK[F, *]]{
    def default[A]: Option[F[A]] = None
  }


  abstract class Cached[F[_]] extends SchemaVisitor[F] {
    protected val cache: CompilationCache[F]

    override def apply[A](schema: Schema[A]): F[A] = {
      cache.getOrElseUpdate(schema, super.apply(_: Schema[A]))
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy