refined icon indicating copy to clipboard operation
refined copied to clipboard

Chaining refined string operation

Open aurrelhebert opened this issue 2 years ago • 1 comments

Context

Hi, I would like to use REFINED to validate some custom input string I have. For some of the string, I would like to chain existing refined string operation as start_with and uuid.

Exemple

The input string I have looks like random_VALID_UUID. At the moment I write a custom refined type as:

final case class PrefixedUUID[S](prefix: S)

object PrefixedUUID {

  implicit def prefixedUUIDValidate[S <: String](
      implicit
      prefix: Witness.Aux[S]
    ): Validate.Plain[String, PrefixedUUID[S]] = {
    Validate.fromPartial(
      s => {
        if (s.startsWith(prefix.value)) {
          val uuid: String = s.stripPrefix(prefix.value)
          require(java.util.UUID.fromString(uuid).toString == uuid.toLowerCase)
        } else {
          throw new Exception("Not a valid UUID")
        }
      },
      s"""PrefixedUUID("${prefix.value}")""",
      PrefixedUUID(prefix.value)
    )
  }
}

Is it the best approach to do it? Can I do it in a more generic way (chaining native refined operation)? If not, maybe can you lead me on how I can contribute a generic way to do it for the core refined library, if you are interested?

Thanks,

aurrelhebert avatar Apr 04 '22 07:04 aurrelhebert

I think my first implementation is a bit limited. Maybe we could implement a more generic Split String function that will allow us to apply a list of predicates.

What I would see would be something like:

Split[N, SplitOp, List[P]]

where n would be the amount of expected splits (example: 2), a split operator (example: Count(2), By("_")) and a predicate list (example: UUID :: URL :: HNil).

We could even create a Partition alias operator that would be:

Partition[SplitOp, P1, P2] = Split[2, SplitOp, P1 :: P2 :: HNil]

aurrelhebert avatar Jan 23 '23 12:01 aurrelhebert