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

shapeless.alacarte.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2014 Miles Sabin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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 shapeless

import scala.reflect.ClassTag

import record._
import ops.hlist.{ Length, Tupler }
import ops.nat.ToInt
import ops.record.Merger

trait CaseClassFacet {
  type C
}

trait ProductISOFacet extends CaseClassFacet {
  trait ProductISOOps {
    type Repr <: HList
    type P <: Product
    val gen: Generic.Aux[C, Repr]
    val pgen: Generic.Aux[P, Repr]

    def toProduct(c: C): P = pgen.from(gen.to(c))
    def fromProduct(p: P): C = gen.from(pgen.to(p))
  }

  val ops: ProductISOOps
}

trait ApplyUnapplyFacet extends ProductISOFacet {
  trait ApplyUnapplyOps extends ProductISOOps {
    def apply(p: P): C = fromProduct(p)

    def unapply(c: C): Option[P] = Some(toProduct(c))
  }

  val ops: ApplyUnapplyOps

  trait ApplyUnapplyCompanion {
    @nonGeneric def apply(elems: ops.P): C = ops.apply(elems)
    @nonGeneric def unapply(s: C): Option[ops.P] = ops.unapply(s)
  }
}

trait ProductFacet extends ProductISOFacet {
  trait ProductOps extends ProductISOOps {
    def productElement(c: C, n: Int): Any = toProduct(c).productElement(n)

    def productIterator(c: C): Iterator[Any] = toProduct(c).productIterator

    def productPrefix: String

    def productArity: Int
  }

  val ops: ProductOps

  trait ProductMethods { self: C =>
    def productElement(n: Int): Any = ops.productElement(this, n)

    def productIterator: Iterator[Any] = ops.productIterator(this)

    def productPrefix: String = ops.productPrefix

    def productArity: Int = ops.productArity
  }
}

trait PolymorphicEqualityFacet extends ProductISOFacet {
  trait PolymorphicEqualityOps extends ProductISOOps {
    val typ: Typeable[C]

    def canEqual(c: C, other: Any): Boolean = typ.cast(other).isDefined

    def equals(c: C, other: Any): Boolean =
      (c.asInstanceOf[AnyRef] eq other.asInstanceOf[AnyRef]) ||
        typ.cast(other).map { that =>
          (toProduct(c) == toProduct(that)) && canEqual(that, c)
        }.getOrElse(false)

    def hashCode(c: C): Int = toProduct(c).hashCode
  }

  val ops: PolymorphicEqualityOps

  trait PolymorphicEqualityMethods { self: C =>
    override def equals(other: Any): Boolean = ops.equals(this, other)

    override def hashCode: Int = ops.hashCode(this)
  }
}

trait CopyFacet extends CaseClassFacet {
  trait CopyOps {
    type LRepr <: HList
    type CopyMerger[R <: HList] = Merger.Aux[LRepr, R, LRepr]

    val lgen: LabelledGeneric.Aux[C, LRepr]

    def copy[R <: HList](c: C, rec: R)(implicit merger: CopyMerger[R]): C =
      lgen.from(lgen.to(c).merge(rec))
  }

  val ops: CopyOps

  trait CopyMethods extends RecordArgs { self: C =>
    def copyRecord[R <: HList](rec: R)(implicit merger: ops.CopyMerger[R]): C = ops.copy(this, rec)
  }
}

trait ToStringFacet extends ProductFacet {
  trait ToStringOps extends ProductOps {
    def toString(c: C): String = productPrefix+toProduct(c).toString
  }

  val ops: ToStringOps

  trait ToStringMethods { self: C =>
    override def toString: String = ops.toString(this)
  }
}

trait DefaultCaseClassDefns extends
  ApplyUnapplyFacet with
  ProductFacet with
  PolymorphicEqualityFacet with
  CopyFacet with
  ToStringFacet {

  trait CaseClassOps extends
    ApplyUnapplyOps with
    ProductOps with
    PolymorphicEqualityOps with
    CopyOps with
    ToStringOps

  trait CaseClassCompanion extends
    ApplyUnapplyCompanion

  trait CaseClass extends
    ProductMethods with
    PolymorphicEqualityMethods with
    CopyMethods with
    ToStringMethods { self: C => }

  val ops: CaseClassOps

  def Ops[Repr0 <: HList, LRepr0 <: HList, P0 <: Product, N <: Nat]
    (implicit
      gen0: Generic.Aux[C, Repr0],
      lgen0: LabelledGeneric.Aux[C, LRepr0],
      len: Length.Aux[Repr0, N],
      toInt: ToInt[N],
      tup: Tupler.Aux[Repr0, P0],
      pgen0: Generic.Aux[P0, Repr0],
      typ0: Typeable[C],
      tag0: ClassTag[C]
    ) =
      new CaseClassOps {
        type Repr = Repr0
        type LRepr = LRepr0
        type P = P0
        val gen = gen0
        val lgen = lgen0
        val pgen = pgen0
        val typ = typ0
        val tag = tag0
        val productPrefix = tag0.runtimeClass.getName.split("(\\.|\\$)").last
        val productArity = toInt()
      }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy