From 8614d0f2c3ecaf31586293e44f9a3052a69357ec Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Thu, 11 Feb 2021 23:37:14 +0100 Subject: [PATCH] Reorganize code and add readme --- README.md | 50 +++++++++++ src/main/kotlin/de/justjanne/bitflags/of.kt | 77 ++++++++++++++++ .../kotlin/de/justjanne/bitflags/toFlag.kt | 90 ------------------- 3 files changed, 127 insertions(+), 90 deletions(-) create mode 100644 README.md delete mode 100644 src/main/kotlin/de/justjanne/bitflags/toFlag.kt diff --git a/README.md b/README.md new file mode 100644 index 0000000..00bc3eb --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +# Kotlin Bitflags + +Kotlin-Bitflags is a utility library to simplify implementing bitflags in Kotlin. It integrates with Kotlin unsigned +types and Java Enumsets. This especially useful when interacting with binary protocols from Kotlin. + +## Using Kotlin-Bitflags + +After adding this module to your dependencies, you'll have to implement the related interfaces in your classes: + +```kotlin +enum class MessageFlag( + override val value: UInt, +) : Flag<UInt> { + Self(0x01u), + Highlight(0x02u), + Redirected(0x04u), + ServerMsg(0x08u), + Backlog(0x80u); + + companion object : Flags<UInt, MessageFlag> { + override val all: Set<MessageFlag> = values().toEnumSet() + } +} +``` + +This allows you to then use this elsewhere to e.g initialize a field from discrete values +```kotlin +// Construct from varargs or an array +val field = MessageFlag.of(MessageFlag.Self, MessageFlag.Highlight) + +val values = listOf(MessageFlag.Self, MessageFlag.Highlight) +// Or from a collection +val field = MessageFlag.of(values) +// Or use the to helper +val field = values.toEnumSet() +``` + +You can also convert such a field into the raw binary value easily +```kotlin +// Returns in this case UInt +field.toBits() +``` + +Additional utility functions are available: +```kotlin +// Empty field +MessageFlag.none() +// Get all non-null values +MessageFlag.validValues() +``` diff --git a/src/main/kotlin/de/justjanne/bitflags/of.kt b/src/main/kotlin/de/justjanne/bitflags/of.kt index 047f12f..e1573d9 100644 --- a/src/main/kotlin/de/justjanne/bitflags/of.kt +++ b/src/main/kotlin/de/justjanne/bitflags/of.kt @@ -11,6 +11,7 @@ package de.justjanne.bitflags import java.util.EnumSet +import kotlin.experimental.and /** * Construct a bitfield out of discrete flags @@ -25,3 +26,79 @@ inline fun <reified T> Flags<*, T>.of(vararg values: T): EnumSet<T> */ inline fun <reified T> Flags<*, T>.of(values: Collection<T>): EnumSet<T> where T : Flag<*>, T : Enum<T> = values.toEnumSet() + +/** + * Construct a bitfield out of a binary value + * @return bitfield + */ +inline fun <reified T> Flags<Byte, T>.of(value: Byte?): EnumSet<T> where T : Flag<Byte>, T : Enum<T> { + if (value == null) return emptyList<T>().toEnumSet() + return all.filter { (value and it.value) != 0.toByte() }.toEnumSet() +} + +/** + * Construct a bitfield out of a binary value + * @return bitfield + */ +@ExperimentalUnsignedTypes +inline fun <reified T> Flags<UByte, T>.of(value: UByte?): EnumSet<T> where T : Flag<UByte>, T : Enum<T> { + if (value == null) return emptyList<T>().toEnumSet() + return all.filter { (value and it.value) != 0.toUByte() }.toEnumSet() +} + +/** + * Construct a bitfield out of a binary value + * @return bitfield + */ +inline fun <reified T> Flags<Short, T>.of(value: Short?): EnumSet<T> where T : Flag<Short>, T : Enum<T> { + if (value == null) return emptyList<T>().toEnumSet() + return all.filter { (value and it.value) != 0.toShort() }.toEnumSet() +} + +/** + * Construct a bitfield out of a binary value + * @return bitfield + */ +@ExperimentalUnsignedTypes +inline fun <reified T> Flags<UShort, T>.of(value: UShort?): EnumSet<T> where T : Flag<UShort>, T : Enum<T> { + if (value == null) return emptyList<T>().toEnumSet() + return all.filter { (value and it.value) != 0.toUShort() }.toEnumSet() +} + +/** + * Construct a bitfield out of a binary value + * @return bitfield + */ +inline fun <reified T> Flags<Int, T>.of(value: Int?): EnumSet<T> where T : Flag<Int>, T : Enum<T> { + if (value == null) return emptyList<T>().toEnumSet() + return all.filter { (value and it.value) != 0 }.toEnumSet() +} + +/** + * Construct a bitfield out of a binary value + * @return bitfield + */ +@ExperimentalUnsignedTypes +inline fun <reified T> Flags<UInt, T>.of(value: UInt?): EnumSet<T> where T : Flag<UInt>, T : Enum<T> { + if (value == null) return emptyList<T>().toEnumSet() + return all.filter { (value and it.value) != 0u }.toEnumSet() +} + +/** + * Construct a bitfield out of a binary value + * @return bitfield + */ +inline fun <reified T> Flags<Long, T>.of(value: Long?): EnumSet<T> where T : Flag<Long>, T : Enum<T> { + if (value == null) return emptyList<T>().toEnumSet() + return all.filter { (value and it.value) != 0L }.toEnumSet() +} + +/** + * Construct a bitfield out of a binary value + * @return bitfield + */ +@ExperimentalUnsignedTypes +inline fun <reified T> Flags<ULong, T>.of(value: ULong?): EnumSet<T> where T : Flag<ULong>, T : Enum<T> { + if (value == null) return emptyList<T>().toEnumSet() + return all.filter { (value and it.value) != 0uL }.toEnumSet() +} diff --git a/src/main/kotlin/de/justjanne/bitflags/toFlag.kt b/src/main/kotlin/de/justjanne/bitflags/toFlag.kt deleted file mode 100644 index 98cb909..0000000 --- a/src/main/kotlin/de/justjanne/bitflags/toFlag.kt +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Kotlin Bitflags - * - * Copyright (c) 2021 Janne Mareike Koschinski - * - * This Source Code Form is subject to the terms of the Mozilla Public License, - * v. 2.0. If a copy of the MPL was not distributed with this file, You can - * obtain one at https://mozilla.org/MPL/2.0/. - */ - -package de.justjanne.bitflags - -import java.util.EnumSet -import kotlin.experimental.and - -/** - * Construct a bitfield out of a binary value - * @return bitfield - */ -inline fun <reified T> Flags<Byte, T>.of(value: Byte?): EnumSet<T> where T : Flag<Byte>, T : Enum<T> { - if (value == null) return emptyList<T>().toEnumSet() - return all.filter { (value and it.value) != 0.toByte() }.toEnumSet() -} - -/** - * Construct a bitfield out of a binary value - * @return bitfield - */ -@ExperimentalUnsignedTypes -inline fun <reified T> Flags<UByte, T>.of(value: UByte?): EnumSet<T> where T : Flag<UByte>, T : Enum<T> { - if (value == null) return emptyList<T>().toEnumSet() - return all.filter { (value and it.value) != 0.toUByte() }.toEnumSet() -} - -/** - * Construct a bitfield out of a binary value - * @return bitfield - */ -inline fun <reified T> Flags<Short, T>.of(value: Short?): EnumSet<T> where T : Flag<Short>, T : Enum<T> { - if (value == null) return emptyList<T>().toEnumSet() - return all.filter { (value and it.value) != 0.toShort() }.toEnumSet() -} - -/** - * Construct a bitfield out of a binary value - * @return bitfield - */ -@ExperimentalUnsignedTypes -inline fun <reified T> Flags<UShort, T>.of(value: UShort?): EnumSet<T> where T : Flag<UShort>, T : Enum<T> { - if (value == null) return emptyList<T>().toEnumSet() - return all.filter { (value and it.value) != 0.toUShort() }.toEnumSet() -} - -/** - * Construct a bitfield out of a binary value - * @return bitfield - */ -inline fun <reified T> Flags<Int, T>.of(value: Int?): EnumSet<T> where T : Flag<Int>, T : Enum<T> { - if (value == null) return emptyList<T>().toEnumSet() - return all.filter { (value and it.value) != 0 }.toEnumSet() -} - -/** - * Construct a bitfield out of a binary value - * @return bitfield - */ -@ExperimentalUnsignedTypes -inline fun <reified T> Flags<UInt, T>.of(value: UInt?): EnumSet<T> where T : Flag<UInt>, T : Enum<T> { - if (value == null) return emptyList<T>().toEnumSet() - return all.filter { (value and it.value) != 0u }.toEnumSet() -} - -/** - * Construct a bitfield out of a binary value - * @return bitfield - */ -inline fun <reified T> Flags<Long, T>.of(value: Long?): EnumSet<T> where T : Flag<Long>, T : Enum<T> { - if (value == null) return emptyList<T>().toEnumSet() - return all.filter { (value and it.value) != 0L }.toEnumSet() -} - -/** - * Construct a bitfield out of a binary value - * @return bitfield - */ -@ExperimentalUnsignedTypes -inline fun <reified T> Flags<ULong, T>.of(value: ULong?): EnumSet<T> where T : Flag<ULong>, T : Enum<T> { - if (value == null) return emptyList<T>().toEnumSet() - return all.filter { (value and it.value) != 0uL }.toEnumSet() -} -- GitLab