Skip to content

Commit 57e962a

Browse files
authored
Merge pull request #1367 from UdashFramework/rest-wrapper-implicits
Rest wrapper implicits
2 parents bc972c2 + e058035 commit 57e962a

File tree

1 file changed

+33
-21
lines changed

1 file changed

+33
-21
lines changed

rest/src/main/scala/io/udash/rest/RestDataCompanion.scala

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package rest
44
import com.avsystem.commons.meta.MacroInstances
55
import com.avsystem.commons.misc.{AbstractValueEnumCompanion, ValueEnum, ValueOf}
66
import com.avsystem.commons.rpc.{AsRaw, AsReal}
7-
import com.avsystem.commons.serialization.{GenCodec, TransparentWrapperCompanion}
7+
import com.avsystem.commons.serialization.{GenCodec, TransparentWrapperCompanion, TransparentWrapping}
88
import io.udash.rest.openapi.*
99
import io.udash.rest.openapi.RestStructure.NameAndAdjusters
1010
import io.udash.rest.raw.{HttpBody, JsonValue, PlainValue, RestResponse, StreamedBody, StreamedRestResponse}
@@ -43,32 +43,23 @@ abstract class RestDataCompanion[T](implicit
4343
* It must be a singleton object type, i.e. `SomeObject.type`.
4444
*/
4545
abstract class RestDataCompanionWithDeps[D, T](implicit
46-
deps: ValueOf[D], instances: MacroInstances[(DefaultRestImplicits, D), CodecWithStructure[T]]
46+
deps: ValueOf[D],
47+
instances: MacroInstances[(DefaultRestImplicits, D), CodecWithStructure[T]],
4748
) extends AbstractRestDataCompanion[(DefaultRestImplicits, D), T]((DefaultRestImplicits, deps.value))
4849

4950
/**
50-
* Base class for companion objects of wrappers over other data types (i.e. case classes with single field).
51-
* This companion ensures instances of all the REST typeclasses (serialization, schema, etc.) for wrapping type
52-
* assuming that these instances are available for the wrapped type.
53-
*
54-
* Using this base companion class makes the wrapper class effectively "transparent", i.e. as if it was annotated with
55-
* [[com.avsystem.commons.serialization.transparent transparent]] annotation.
51+
* These implicits must be specialized for every raw type (PlainValue, JsonValue, etc.) because
52+
* it lifts their priority. Unfortunately, controlling implicit priority is not pretty.
53+
* Also, it's probably good that we explicitly enable derivation only for REST-related raw types
54+
* and not for all raw types - this avoids possible interference with other features using RPC.
5655
*
57-
* @example
58-
* {{{
59-
* case class UserId(id: String) extends AnyVal
60-
* object UserId extends RestDataWrapperCompanion[String, UserId]
61-
* }}}
56+
* Seperated from [[RestDataWrapperCompanion]] to allow creating custom companion wrappers.
6257
*/
63-
abstract class RestDataWrapperCompanion[Wrapped, T](implicit
64-
instances: MacroInstances[DefaultRestImplicits, () => NameAndAdjusters[T]]
65-
) extends TransparentWrapperCompanion[Wrapped, T] {
66-
private def nameAndAdjusters: NameAndAdjusters[T] = instances(DefaultRestImplicits, this).apply()
58+
trait RestDataWrapperImplicits[Wrapped, T] {
59+
protected def nameAndAdjusters: NameAndAdjusters[T]
60+
protected def wrapping: TransparentWrapping[Wrapped, T]
6761

68-
// These implicits must be specialized for every raw type (PlainValue, JsonValue, etc.) because
69-
// it lifts their priority. Unfortunately, controlling implicit priority is not pretty.
70-
// Also, it's probably good that we explicitly enable derivation only for REST-related raw types
71-
// and not for all raw types - this avoids possible interference with other features using RPC.
62+
private implicit def wrappingAsImplicit: TransparentWrapping[Wrapped, T] = wrapping
7263

7364
implicit def plainAsRaw(implicit wrappedAsRaw: AsRaw[PlainValue, Wrapped]): AsRaw[PlainValue, T] =
7465
AsRaw.fromTransparentWrapping
@@ -122,6 +113,27 @@ abstract class RestDataWrapperCompanion[Wrapped, T](implicit
122113
wrappedResponses.responses(resolver, ws => schemaTransform(nameAndAdjusters.restSchema(ws)))
123114
}
124115

116+
/**
117+
* Base class for companion objects of wrappers over other data types (i.e. case classes with single field).
118+
* This companion ensures instances of all the REST typeclasses (serialization, schema, etc.) for wrapping type
119+
* assuming that these instances are available for the wrapped type.
120+
*
121+
* Using this base companion class makes the wrapper class effectively "transparent", i.e. as if it was annotated with
122+
* [[com.avsystem.commons.serialization.transparent transparent]] annotation.
123+
*
124+
* @example
125+
* {{{
126+
* case class UserId(id: String) extends AnyVal
127+
* object UserId extends RestDataWrapperCompanion[String, UserId]
128+
* }}}
129+
*/
130+
abstract class RestDataWrapperCompanion[Wrapped, T](implicit
131+
instances: MacroInstances[DefaultRestImplicits, () => NameAndAdjusters[T]]
132+
) extends TransparentWrapperCompanion[Wrapped, T] with RestDataWrapperImplicits[Wrapped, T] {
133+
override protected final def nameAndAdjusters: NameAndAdjusters[T] = instances(DefaultRestImplicits, this).apply()
134+
override protected final def wrapping: TransparentWrapping[Wrapped, T] = this
135+
}
136+
125137
/**
126138
* Base class for companion objects of enum types [[ValueEnum]] which are used as
127139
* parameter or result types in REST API traits. Automatically provides instance of

0 commit comments

Comments
 (0)