From b2574e67305954dae04947448961793fb095e161 Mon Sep 17 00:00:00 2001 From: David Denton Date: Mon, 11 Sep 2017 08:32:16 +0100 Subject: [PATCH] started introducing lenses --- src/test/scala/lens/LensExtractor.scala | 17 ++++++++ src/test/scala/lens/LensInjector.scala | 18 ++++++++ src/test/scala/lens/Lenses.scala | 55 +++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 src/test/scala/lens/LensExtractor.scala create mode 100644 src/test/scala/lens/LensInjector.scala create mode 100644 src/test/scala/lens/Lenses.scala diff --git a/src/test/scala/lens/LensExtractor.scala b/src/test/scala/lens/LensExtractor.scala new file mode 100644 index 00000000..4969e202 --- /dev/null +++ b/src/test/scala/lens/LensExtractor.scala @@ -0,0 +1,17 @@ +package lens + +trait LensExtractor[IN, OUT] extends Function[IN, OUT] { + /** + * Lens operation to get the value from the target + * + * @throws LensFailure if the value could not be retrieved from the target (missing/invalid etc) + */ + override def apply(target: IN): OUT + + /** + * Lens operation to get the value from the target. Synonym for invoke(IN) + * + * @throws LensFailure if the value could not be retrieved from the target (missing/invalid etc) + */ + def extract(target: IN): OUT = apply(target) +} diff --git a/src/test/scala/lens/LensInjector.scala b/src/test/scala/lens/LensInjector.scala new file mode 100644 index 00000000..ebf89293 --- /dev/null +++ b/src/test/scala/lens/LensInjector.scala @@ -0,0 +1,18 @@ +package lens + +trait LensInjector[IN, OUT] { + /** + * Lens operation to set the value into the target + */ + def apply[R <: IN](value: OUT, target: R): R + + /** + * Lens operation to set the value into the target. Synomym for invoke(OUT, IN) + */ + def inject[R <: IN](value: OUT, target: R): R = apply(value, target) + + /** + * Bind this Lens to a value, so we can set it into a target + */ + def of[R <: IN](value: OUT): (R) => R = apply(value, _) +} diff --git a/src/test/scala/lens/Lenses.scala b/src/test/scala/lens/Lenses.scala new file mode 100644 index 00000000..009ca595 --- /dev/null +++ b/src/test/scala/lens/Lenses.scala @@ -0,0 +1,55 @@ +package lens + +import io.fintrospect.parameters.ParamType + +class LensGet[IN, MID, OUT] private(private val rootFn: (String, IN) => List[MID], private val fn: (MID) => OUT) { + def map[NEXT](nextFn: (OUT) => NEXT): LensGet[IN, MID, NEXT] = new LensGet[IN, MID, NEXT](rootFn, (i: MID) => nextFn(fn(i))) +} + +object LensGet { + def apply[IN, OUT](rootFn: (String, IN) => List[OUT]): LensGet[IN, OUT, OUT] = new LensGet(rootFn, (i: OUT) => i) +} + +class LensSet[IN, MID, OUT] private(private val rootFn: (String, List[MID], IN) => IN, private val fn: (OUT) => MID) { + def map[NEXT](nextFn: (NEXT) => OUT): LensSet[IN, MID, NEXT] = new LensSet[IN, MID, NEXT](rootFn, (value: NEXT) => fn(nextFn(value))) +} + +object LensSet { + def apply[IN, OUT](rootFn: (String, List[OUT], IN) => IN): LensSet[IN, OUT, OUT] = new LensSet(rootFn, (i: OUT) => i) +} + +///** +// * A Lens provides the uni-directional extraction of an entity from a target. +// */ +// class Lens[IN, FINAL](val meta: Meta, +//private val get: (IN) =] FINAL) : LensExtractor[IN, FINAL], Iterable[Meta] { +// +// import shapeless.PolyDefns.=] +// +// override defiterator(): Iterator[Meta] = listOf(meta).iterator() +// +// override deftoString(): String = "${if (meta.required) "Required" else "Optional"} ${meta.location} '${meta.name}'" +// +// override definvoke(target: IN): FINAL = try { +// get(target) +//} catch (e: LensFailure) { +// throw e +//} catch (e: Exception) { +// throw LensFailure(Invalid(meta), cause = e) +//} +//} +// +// /** +// * A BiDiLens provides the bi-directional extraction of an entity from a target, or the insertion of an entity +// * into a target. +// */ +// class BiDiLens[IN, FINAL](meta: Meta, +// get: (IN) =] FINAL, +// private val set: (FINAL, IN) =] IN) : LensInjector[IN, FINAL], Lens[IN, FINAL](meta, get) { +// +// @Suppress("UNCHECKED_CAST") +// override def[R : IN] invoke(value: FINAL, target: R): R = set(value, target) as R +//} + + +case class Meta(required: Boolean, location: String, paramMeta: ParamType, name: String, description: Option[String] = null) \ No newline at end of file