Skip to content

[pureconfig] Refined keys for Map[String, T] #443

Open
@NeQuissimus

Description

PureConfig provides an instance of ConfigReader for maps. (see https://github.com/pureconfig/pureconfig/blob/v0.9.0/core/src/main/scala/pureconfig/DerivedReaders.scala#L198)

Unfortunately, it seems impossible to provide a refinement for the map key without writing a custom ConfigReader
I think refined should provide a ConfigReader[Map[Refined[String, ?], T]] that would allow for map keys to be something like String Refined MaxSize[W.249.T].

I attempted to create such a ConfigReader but failed to provide a generic definition.

I did, however, manage to make a specific one for my use case (Kafka topics), so maybe that can help:

// https://github.com/apache/kafka/blob/1.0.0/clients/src/main/java/org/apache/kafka/common/internals/Topic.java
  type TopicSpec = NonEmpty And MaxSize[W.`249`.T] And MatchesRegex[W.`"[a-zA-Z0-9\\\\.\\\\-_]+"`.T] And Not[Equal[W.`"."`.T]] And Not[Equal[W.`".."`.T]]
  type Topic = String Refined TopicSpec

  implicit def deriveTopicMap[T](implicit reader: Derivation[Lazy[ConfigReader[T]]]): ConfigReader[Map[Topic, T]] = new ConfigReader[Map[Topic, T]] {
    override def from(cur: ConfigCursor): Either[ConfigReaderFailures, Map[Topic, T]] = {
      cur.asMap.right.flatMap { map =>
        map.foldLeft[Either[ConfigReaderFailures, Map[Topic, T]]](Right(Map())) {
          case (acc, (key, valueConf)) => {
              val topic = refineV[TopicSpec](key)
              topic.map { key =>
                combineResults(acc, reader.value.value.from(valueConf)) { (map, value) => map + (key -> value) }
              }.getOrElse(Right(Map.empty[Topic, T]))
            }
        }
      }
    }
  }

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions