package com.hypixel.hytale.codec.codecs.map;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.ExtraInfo;
import com.hypixel.hytale.codec.WrappedCodec;
import com.hypixel.hytale.codec.exception.CodecException;
import com.hypixel.hytale.codec.schema.SchemaContext;
import com.hypixel.hytale.codec.schema.config.ObjectSchema;
import com.hypixel.hytale.codec.schema.config.Schema;
import com.hypixel.hytale.codec.schema.config.StringSchema;
import com.hypixel.hytale.codec.util.RawJsonReader;
import it.unimi.dsi.fastutil.floats.Float2ObjectMap;
import it.unimi.dsi.fastutil.floats.Float2ObjectMaps;
import java.io.IOException;
import java.util.Map;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import org.bson.BsonDocument;
import org.bson.BsonValue;
public class Float2ObjectMapCodec<T> implements Codec<Float2ObjectMap<T>>, WrappedCodec<T> {
public static final Pattern FLOAT_PATTERN = Pattern.compile("^[-+]?[0-9]+(.[0-9]+)?$");
private final Codec<T> valueCodec;
private final Supplier<Float2ObjectMap<T>> supplier;
private final boolean unmodifiable;
public Float2ObjectMapCodec(Codec<T> valueCodec, Supplier<Float2ObjectMap<T>> supplier, boolean unmodifiable) {
this.valueCodec = valueCodec;
this.supplier = supplier;
this.unmodifiable = unmodifiable;
}
public Float2ObjectMapCodec(Codec<T> valueCodec, Supplier<Float2ObjectMap<T>> supplier) {
this(valueCodec, supplier, true);
}
public Codec<T> getChildCodec() {
return this.valueCodec;
}
public Float2ObjectMap<T> decode(@Nonnull BsonValue bsonValue, @Nonnull ExtraInfo extraInfo) {
BsonDocument bsonDocument = bsonValue.asDocument();
Float2ObjectMap<T> map = (Float2ObjectMap)this.supplier.get();
for(Map.Entry<String, BsonValue> entry : bsonDocument.entrySet()) {
String key = (String)entry.getKey();
BsonValue value = (BsonValue)entry.getValue();
extraInfo.pushKey(key);
try {
float decodedKey = Float.parseFloat(key);
map.put(decodedKey, this.valueCodec.decode(value, extraInfo));
} catch (Exception e) {
throw new CodecException("Failed to decode", value, extraInfo, e);
} finally {
extraInfo.popKey();
}
}
if (this.unmodifiable) {
map = Float2ObjectMaps.<T>unmodifiable(map);
}
return map;
}
@Nonnull
public BsonValue encode(@Nonnull Float2ObjectMap<T> map, ExtraInfo extraInfo) {
BsonDocument bsonDocument = new BsonDocument();
for(Float2ObjectMap.Entry<T> entry : map.float2ObjectEntrySet()) {
bsonDocument.put(Float.toString(entry.getFloatKey()), this.valueCodec.encode(entry.getValue(), extraInfo));
}
return bsonDocument;
}
public Float2ObjectMap<T> decodeJson(@Nonnull RawJsonReader reader, @Nonnull ExtraInfo extraInfo) throws IOException {
reader.expect('{');
reader.consumeWhiteSpace();
Float2ObjectMap<T> map = (Float2ObjectMap)this.supplier.get();
if (reader.tryConsume('}')) {
if (this.unmodifiable) {
map = Float2ObjectMaps.<T>unmodifiable(map);
}
return map;
} else {
while(true) {
String key = reader.readString();
reader.consumeWhiteSpace();
reader.expect(':');
reader.consumeWhiteSpace();
extraInfo.pushKey(key, reader);
try {
float decodedKey = Float.parseFloat(key);
map.put(decodedKey, this.valueCodec.decodeJson(reader, extraInfo));
} catch (Exception e) {
throw new CodecException("Failed to decode", reader, extraInfo, e);
} finally {
extraInfo.popKey();
}
reader.consumeWhiteSpace();
if (reader.tryConsumeOrExpect('}', ',')) {
if (this.unmodifiable) {
map = Float2ObjectMaps.<T>unmodifiable(map);
}
return map;
}
reader.consumeWhiteSpace();
}
}
}
@Nonnull
public Schema toSchema(@Nonnull SchemaContext context) {
ObjectSchema s = new ObjectSchema();
StringSchema name = new StringSchema();
name.setPattern(FLOAT_PATTERN);
name.setMarkdownDescription("A string that contains any floating point number");
s.setPropertyNames(name);
s.setAdditionalProperties(context.refDefinition(this.valueCodec));
return s;
}
}