@@ -2,68 +2,71 @@ package com.avsystem.commons
2
2
package hocon
3
3
4
4
import com .avsystem .commons .meta .MacroInstances
5
- import com .avsystem .commons .misc .ValueOf
6
- import com .avsystem .commons .serialization .{GenCodec , GenKeyCodec , GenObjectCodec , HasGenObjectCodecWithDeps }
7
5
import com .avsystem .commons .serialization .GenCodec .ReadFailure
6
+ import com .avsystem .commons .serialization .{GenCodec , GenKeyCodec , GenObjectCodec }
8
7
import com .typesafe .config .{Config , ConfigFactory , ConfigObject }
9
8
10
9
import scala .concurrent .duration .*
11
10
12
- trait CommonsHoconCodecs {
13
- implicit final val configCodec : GenCodec [Config ] = GenCodec .nullable(
11
+ trait HoconGenCodecs {
12
+ implicit def configCodec : GenCodec [Config ] = HoconGenCodecs .ConfigCodec
13
+ implicit def finiteDurationCodec : GenCodec [FiniteDuration ] = HoconGenCodecs .FiniteDurationCodec
14
+ implicit def sizeInBytesCodec : GenCodec [SizeInBytes ] = HoconGenCodecs .SizeInBytesCodec
15
+ implicit def classKeyCodec : GenKeyCodec [Class [? ]] = HoconGenCodecs .ClassKeyCodec
16
+ implicit def classCodec : GenCodec [Class [? ]] = HoconGenCodecs .ClassCodec
17
+ }
18
+ object HoconGenCodecs {
19
+ implicit final val ConfigCodec : GenCodec [Config ] = GenCodec .nullable(
14
20
input =>
15
- input.readCustom(ConfigValueMarker ).map {
21
+ input.readCustom(ConfigValueMarker ).fold( ConfigFactory .parseString(input.readSimple().readString())) {
16
22
case obj : ConfigObject => obj.toConfig
17
23
case v => throw new ReadFailure (s " expected a config OBJECT, got ${v.valueType}" )
18
- }.getOrElse {
19
- ConfigFactory .parseString(input.readSimple().readString())
20
24
},
21
25
(output, value) =>
22
26
if (! output.writeCustom(ConfigValueMarker , value.root)) {
23
27
output.writeSimple().writeString(value.root.render)
24
28
},
25
29
)
26
30
27
- implicit final val finiteDurationCodec : GenCodec [FiniteDuration ] = GenCodec .nullable(
31
+ implicit final val FiniteDurationCodec : GenCodec [FiniteDuration ] = GenCodec .nullable(
28
32
input => input.readCustom(DurationMarker ).fold(input.readSimple().readLong())(_.toMillis).millis,
29
33
(output, value) => output.writeSimple().writeLong(value.toMillis),
30
34
)
31
35
32
- implicit final val sizeInBytesCodec : GenCodec [SizeInBytes ] = GenCodec .nonNull(
36
+ implicit final val SizeInBytesCodec : GenCodec [SizeInBytes ] = GenCodec .nonNull(
33
37
input => SizeInBytes (input.readCustom(SizeInBytesMarker ).getOrElse(input.readSimple().readLong())),
34
38
(output, value) => output.writeSimple().writeLong(value.bytes),
35
39
)
36
40
37
- implicit final val classKeyCodec : GenKeyCodec [Class [? ]] =
41
+ implicit final val ClassKeyCodec : GenKeyCodec [Class [? ]] =
38
42
GenKeyCodec .create(Class .forName, _.getName)
39
43
40
- implicit final val classCodec : GenCodec [Class [? ]] =
44
+ implicit final val ClassCodec : GenCodec [Class [? ]] =
41
45
GenCodec .nullableString(Class .forName, _.getName)
42
46
}
43
- object CommonsHoconCodecs extends CommonsHoconCodecs
47
+
48
+ object DefaultHoconGenCodecs extends HoconGenCodecs
49
+
50
+ trait ConfigObjectCodec [T ] {
51
+ def objectCodec : GenObjectCodec [T ]
52
+ }
53
+
54
+ abstract class AbstractConfigCompanion [Implicits <: HoconGenCodecs , T ](
55
+ implicits : Implicits
56
+ )(implicit instances : MacroInstances [Implicits , ConfigObjectCodec [T ]]
57
+ ) {
58
+ implicit lazy val codec : GenCodec [T ] = instances(implicits, this ).objectCodec
59
+
60
+ final def read (config : Config ): T = HoconInput .read[T ](config)
61
+ }
44
62
45
63
/**
46
64
* Base class for companion objects of configuration case classes and sealed traits
47
65
* (typically deserialized from HOCON files).
48
66
*
49
- * [[ConfigCompanion ]] is equivalent to [[com.avsystem.commons.serialization.HasGenCodec HasGenCodec ]]
50
- * except that it automatically imports codecs from [[CommonsHoconCodecs ]] - codecs for third party types often used
67
+ * [[DefaultConfigCompanion ]] is equivalent to [[com.avsystem.commons.serialization.HasGenCodec HasGenCodec ]]
68
+ * except that it automatically imports codecs from [[HoconGenCodecs ]] - codecs for third party types often used
51
69
* in configuration.
52
70
*/
53
- abstract class ConfigCompanion [T ](implicit
54
- macroCodec : MacroInstances [CommonsHoconCodecs .type , () => GenObjectCodec [T ]],
55
- ) extends HasGenObjectCodecWithDeps [CommonsHoconCodecs .type , T ] {
56
- final def read (config : Config ): T = HoconInput .read[T ](config)
57
- }
58
-
59
- /**
60
- * A version of [[ConfigCompanion ]] which injects additional implicits into macro materialization.
61
- * Implicits are imported from an object specified with type parameter `D`.
62
- * It must be a singleton object type, i.e. `SomeObject.type`.
63
- */
64
- abstract class ConfigCompanionWithDeps [T , D <: CommonsHoconCodecs ](implicit
65
- deps : ValueOf [D ],
66
- macroCodec : MacroInstances [D , () => GenObjectCodec [T ]],
67
- ) extends HasGenObjectCodecWithDeps [D , T ] {
68
- final def read (config : Config ): T = HoconInput .read[T ](config)
69
- }
71
+ abstract class DefaultConfigCompanion [T ](implicit macroCodec : MacroInstances [HoconGenCodecs , ConfigObjectCodec [T ]])
72
+ extends AbstractConfigCompanion [HoconGenCodecs , T ](DefaultHoconGenCodecs )
0 commit comments