package net.minecraft.util; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.DynamicOps; import net.minecraft.nbt.Tag; public class EncoderCache { final LoadingCache, DataResult> cache; public EncoderCache(int maxSize) { this.cache = CacheBuilder.newBuilder().maximumSize(maxSize).concurrencyLevel(1).softValues().build(new CacheLoader, DataResult>() { public DataResult load(EncoderCache.Key key) { return key.resolve(); } }); } public Codec wrap(Codec codec) { return new Codec() { @Override public DataResult> decode(DynamicOps dynamicOps, T object) { return codec.decode(dynamicOps, object); } @Override public DataResult encode(A object, DynamicOps dynamicOps, T object2) { return EncoderCache.this.cache .getUnchecked(new EncoderCache.Key<>(codec, object, dynamicOps)) .map(objectx -> objectx instanceof Tag tag ? tag.copy() : objectx); } }; } record Key(Codec codec, A value, DynamicOps ops) { public DataResult resolve() { return this.codec.encodeStart(this.ops, this.value); } public boolean equals(Object object) { if (this == object) { return true; } else { return !(object instanceof EncoderCache.Key key) ? false : this.codec == key.codec && this.value.equals(key.value) && this.ops.equals(key.ops); } } public int hashCode() { int i = System.identityHashCode(this.codec); i = 31 * i + this.value.hashCode(); return 31 * i + this.ops.hashCode(); } } }