@@ -2,68 +2,71 @@ package com.avsystem.commons
22package hocon
33
44import com .avsystem .commons .meta .MacroInstances
5- import com .avsystem .commons .misc .ValueOf
6- import com .avsystem .commons .serialization .{GenCodec , GenKeyCodec , GenObjectCodec , HasGenObjectCodecWithDeps }
75import com .avsystem .commons .serialization .GenCodec .ReadFailure
6+ import com .avsystem .commons .serialization .{GenCodec , GenKeyCodec , GenObjectCodec }
87import com .typesafe .config .{Config , ConfigFactory , ConfigObject }
98
109import scala .concurrent .duration .*
1110
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(
1420 input =>
15- input.readCustom(ConfigValueMarker ).map {
21+ input.readCustom(ConfigValueMarker ).fold( ConfigFactory .parseString(input.readSimple().readString())) {
1622 case obj : ConfigObject => obj.toConfig
1723 case v => throw new ReadFailure (s " expected a config OBJECT, got ${v.valueType}" )
18- }.getOrElse {
19- ConfigFactory .parseString(input.readSimple().readString())
2024 },
2125 (output, value) =>
2226 if (! output.writeCustom(ConfigValueMarker , value.root)) {
2327 output.writeSimple().writeString(value.root.render)
2428 },
2529 )
2630
27- implicit final val finiteDurationCodec : GenCodec [FiniteDuration ] = GenCodec .nullable(
31+ implicit final val FiniteDurationCodec : GenCodec [FiniteDuration ] = GenCodec .nullable(
2832 input => input.readCustom(DurationMarker ).fold(input.readSimple().readLong())(_.toMillis).millis,
2933 (output, value) => output.writeSimple().writeLong(value.toMillis),
3034 )
3135
32- implicit final val sizeInBytesCodec : GenCodec [SizeInBytes ] = GenCodec .nonNull(
36+ implicit final val SizeInBytesCodec : GenCodec [SizeInBytes ] = GenCodec .nonNull(
3337 input => SizeInBytes (input.readCustom(SizeInBytesMarker ).getOrElse(input.readSimple().readLong())),
3438 (output, value) => output.writeSimple().writeLong(value.bytes),
3539 )
3640
37- implicit final val classKeyCodec : GenKeyCodec [Class [? ]] =
41+ implicit final val ClassKeyCodec : GenKeyCodec [Class [? ]] =
3842 GenKeyCodec .create(Class .forName, _.getName)
3943
40- implicit final val classCodec : GenCodec [Class [? ]] =
44+ implicit final val ClassCodec : GenCodec [Class [? ]] =
4145 GenCodec .nullableString(Class .forName, _.getName)
4246}
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+ }
4462
4563/**
4664 * Base class for companion objects of configuration case classes and sealed traits
4765 * (typically deserialized from HOCON files).
4866 *
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
5169 * in configuration.
5270 */
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