Search code examples
kotlingenericsbit-manipulationenumset

EnumSet of bit flags into UInt in Kotlin


I have a lot of enum class in my Kotlin application. They all represent bit flags that I need to convert between EnumSet<> and UInt for serial communication with an FPGA board.

How can I provide some extension methods that apply to all those Enums?

Enums don't allow class inheritance. EnumSet can't reference an interface. I'm not sure what else to try.

Thanks!

enum class ReadFlag(val bits: UInt) {
  DATA_READY(1u)
  BUSY(2u)
}

typealias ReadFlags = EnumSet<ReadFlag>

enum class WriteFlag(val bits: UInt) {
  UART_RESET(1u)
  BUSY(2u)
  PAGE_DATA(4u)
}

typealias WriteFlags = EnumSet<WriteFlag>

fun ReadFlags.asUInt(): UInt =
    this.fold(0u) { acc, next -> acc or next.bits }

fun WriteFlags.asUInt(): UInt =
    this.fold(0u) { acc, next -> acc or next.bits }

This results in this error:

error: platform declaration clash: The following declarations have the same JVM signature (asUInt(Ljava/util/EnumSet;)I):

Solution

  • Write an interface for the common members:

    interface Flags {
        val bits: UInt
    }
    

    Implement the interface:

    enum class ReadFlag(override val bits: UInt): Flags {
        DATA_READY(1u),
        BUSY(2u)
    }
    
    enum class WriteFlag(override val bits: UInt): Flags {
        UART_RESET(1u),
        BUSY(2u),
        PAGE_DATA(4u)
    }
    

    Then you can make your asUInt generic:

    fun <E> EnumSet<E>.asUInt(): UInt where E : Enum<E>, E: Flags =
        this.fold(0u) { acc, next -> acc or next.bits }