diff options
| -rw-r--r-- | src/main/java/at/hannibal2/skyhanni/utils/const/Const.kt | 38 | ||||
| -rw-r--r-- | src/main/java/at/hannibal2/skyhanni/utils/const/ConstItemStack.kt | 48 |
2 files changed, 86 insertions, 0 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/const/Const.kt b/src/main/java/at/hannibal2/skyhanni/utils/const/Const.kt new file mode 100644 index 000000000..8da2498e0 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/const/Const.kt @@ -0,0 +1,38 @@ +package at.hannibal2.skyhanni.utils.const + +@JvmInline +/** + * Immutable view of an object. + * This class wraps an [T] indicating that it should not be modified. This allows multiple users to share an + * object instance without having to fear that the internal mutability of the object causes unexpected behaviour. + * More specifically, as long as the invariants of the methods and constructors are followed by all users then data + * contained within will never change. + * + * For specific [T]s there are extension methods allowing to safely access the data. + * + * This is a [JvmInline] class, so at + * runtime [Const] is a 0 cost wrapper. + */ +value class Const<T> private constructor( + /** + * Unsafely access the underlying object. Callers of this method promise not to modify the returned instance, or to + * leak this instance to any other codepaths which modify the instance. Whenever possible callers should wrap + * objects they return which offer a view into this object into a [Const] of its own. + */ + @PublishedApi + internal val unsafeMutable: T, +) { + companion object { + /** + * Create a new [Const] instance. Callers of this method guarantee that the given object will not be mutated + * internally. This should ideally be done by every instance of [value] being wrapped in a [Const] (and other + * references to be discarded as quickly as possible). + */ + fun <T> fromOwned(value: T): Const<T> { + return Const(value) + } + } +} + + + diff --git a/src/main/java/at/hannibal2/skyhanni/utils/const/ConstItemStack.kt b/src/main/java/at/hannibal2/skyhanni/utils/const/ConstItemStack.kt new file mode 100644 index 000000000..5e9484ffd --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/const/ConstItemStack.kt @@ -0,0 +1,48 @@ +package at.hannibal2.skyhanni.utils.const + +import net.minecraft.item.EnumDyeColor +import net.minecraft.item.Item +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound + +/** + * Access a shallow copy of the underlying item stack. Callers of this method promise not to modify the nbt data of + * the returned instance, but can modify the stack size, metadata, item or outright replace the root tag compound. + * Interior immutability of [ItemStack.stackTagCompound] needs to be guaranteed by the caller. The instance is owned + * ergo not shared with anyone else, so that there are no mutability concerns about the ItemStack instance itself. + */ +fun Const<ItemStack>.getOwnedShallowCopy(): ItemStack { + return ItemStack(unsafeMutable.item, unsafeMutable.stackSize, unsafeMutable.metadata, unsafeMutable.tagCompound) +} + +/** + * Access a copy of the underlying item stack. The returned copy is fully and deeply owned, so changes can be made + * to the item stack instance, including interior mutability concerning the [ItemStack.stackTagCompound]. + */ +fun Const<ItemStack>.getOwnedDeepCopy(): ItemStack { + return unsafeMutable.copy() +} + +/** + * Returns the [ItemStack.stackSize] + */ +inline val Const<ItemStack>.stackSize: Int get() = unsafeMutable.stackSize + +/** + * Returns the [item type](ItemStack.item) + */ +inline val Const<ItemStack>.itemType: Item get() = unsafeMutable.item + +/** + * Returns the [damage or metadata](ItemStack.metadata) + */ +inline val Const<ItemStack>.damage: Int get() = unsafeMutable.metadata + +/** + * Interprets the [damage] of this item as a [color](EnumDyeColor). This is only valid for some [item types](itemType), + * so check that one first. + */ +inline val Const<ItemStack>.color: EnumDyeColor get() = EnumDyeColor.byDyeDamage(damage) + +inline val Const<ItemStack>.nbt: Const<NBTTagCompound>? + get() = unsafeMutable.tagCompound?.let(Const.Companion::fromOwned) |
