1
1
package refined4s .modules .circe .derivation .generic
2
2
3
- import io .circe .{Decoder , Encoder }
3
+ import io .circe .{Decoder , Encoder , KeyDecoder , KeyEncoder }
4
4
import refined4s .modules .cats .syntax .contraCoercible
5
5
import refined4s .{Coercible , RefinedCtor }
6
6
@@ -17,5 +17,34 @@ trait auto {
17
17
18
18
inline given derivedRefinedDecoder [A , B ](using refinedCtor : RefinedCtor [B , A ], decoder : Decoder [A ]): Decoder [B ] =
19
19
decoder.emap(refinedCtor.create)
20
+
21
+ inline given derivedKeyEncoder [A , B ](using coercible : Coercible [A , B ], encoder : KeyEncoder [B ]): KeyEncoder [A ] =
22
+ contraCoercible(encoder)
23
+
24
+ inline given derivedNewtypeKeyDecoder [A , B ](using coercible : Coercible [A , B ], decoder : KeyDecoder [A ]): KeyDecoder [B ] =
25
+ Coercible .unsafeWrapTC(decoder)
26
+
27
+ inline given derivedRefinedKeyDecoder [A , B ](using refinedCtor : RefinedCtor [B , A ], decoder : KeyDecoder [A ]): KeyDecoder [B ] with {
28
+ override def apply (key : String ): Option [B ] =
29
+ decoder.apply(key).flatMap(refinedCtor.create(_).toOption)
30
+ }
31
+
32
+ /** Without this, Circe's decode uses an incorrect Decoder for the value.
33
+ * @example
34
+ * {{{
35
+ * // when
36
+ * decode[Map[PortNumber, Int]]("""{ "0": 65536 }""")
37
+ *
38
+ * // The expected result is
39
+ * Map(PortNumber(0), 65536)
40
+ *
41
+ * // But the actual result is
42
+ * // Either[DecodingFailure, Map[PortNumber, Int]] =
43
+ * // Left(DecodingFailure(Invalid value: [65536]. It has to be Int between 0 and 65535 (0 <= PortNumber <= 65535), List(DownField(0))))
44
+ * // The KeyDecoder is fine here, but the value Decoder `decode` uses is not Decoder[Int] but Decoder[PortNumber].
45
+ * }}}
46
+ */
47
+ inline given derivedMapDecoder [A , B ](using KeyDecoder [A ], Decoder [B ]): Decoder [Map [A , B ]] = io.circe.Decoder .decodeMap
48
+
20
49
}
21
50
object auto extends auto
0 commit comments