All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.activej.serializer.def.AbstractMapSerializerDef Maven / Gradle / Ivy

/*
 * Copyright (C) 2020 ActiveJ LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.activej.serializer.def;

import io.activej.codegen.expression.Expression;
import io.activej.codegen.expression.Variable;
import io.activej.serializer.CompatibilityLevel;

import java.util.function.BinaryOperator;

import static io.activej.codegen.expression.Expressions.*;
import static io.activej.serializer.CompatibilityLevel.LEVEL_3;
import static io.activej.serializer.def.SerializerExpressions.*;

public abstract class AbstractMapSerializerDef extends AbstractSerializerDef implements SerializerDefWithNullable {
	protected final SerializerDef keySerializer;
	protected final SerializerDef valueSerializer;
	protected final Class encodeType;
	protected final Class decodeType;
	protected final Class keyType;
	protected final Class valueType;
	protected final boolean nullable;

	protected AbstractMapSerializerDef(SerializerDef keySerializer, SerializerDef valueSerializer, Class encodeType, Class decodeType, Class keyType, Class valueType, boolean nullable) {
		this.keySerializer = keySerializer;
		this.valueSerializer = valueSerializer;
		this.encodeType = encodeType;
		this.decodeType = decodeType;
		this.keyType = keyType;
		this.valueType = valueType;
		this.nullable = nullable;
	}

	@Override
	public void accept(Visitor visitor) {
		visitor.visit("key", keySerializer);
		visitor.visit("value", valueSerializer);
	}

	@Override
	public boolean isInline(int version, CompatibilityLevel compatibilityLevel) {
		return false;
	}

	@Override
	public Class getEncodeType() {
		return encodeType;
	}

	@Override
	public Class getDecodeType() {
		return decodeType;
	}

	public SerializerDef getKeySerializer() {
		return keySerializer;
	}

	public SerializerDef getValueSerializer() {
		return valueSerializer;
	}

	public Class getKeyType() {
		return keyType;
	}

	public Class getValueType() {
		return valueType;
	}

	public boolean isNullable() {
		return nullable;
	}

	@Override
	public final SerializerDef ensureNullable(CompatibilityLevel compatibilityLevel) {
		if (compatibilityLevel.getLevel() < LEVEL_3.getLevel()) {
			return SerializerDefs.ofNullable(this);
		}
		return doEnsureNullable(compatibilityLevel);
	}

	@Override
	public final Expression encode(StaticEncoders staticEncoders, Expression buf, Variable pos, Expression value, int version, CompatibilityLevel compatibilityLevel) {
		if (!nullable) {
			return sequence(
				writeVarInt(buf, pos, length(value)),
				doEncode(staticEncoders, buf, pos, value, version, compatibilityLevel));
		} else {
			return ifNull(value,
				writeByte(buf, pos, value((byte) 0)),
				sequence(
					writeVarInt(buf, pos, inc(length(value))),
					doEncode(staticEncoders, buf, pos, value, version, compatibilityLevel)));
		}
	}

	protected Expression doEncode(StaticEncoders staticEncoders, Expression buf, Variable pos, Expression value, int version, CompatibilityLevel compatibilityLevel) {
		Encoder keyEncoder = keySerializer.defineEncoder(staticEncoders, version, compatibilityLevel);
		Encoder valueEncoder = valueSerializer.defineEncoder(staticEncoders, version, compatibilityLevel);
		return doIterateMap(value,
			(k, v) -> sequence(
				keyEncoder.encode(buf, pos, cast(k, keySerializer.getEncodeType())),
				valueEncoder.encode(buf, pos, cast(v, valueSerializer.getEncodeType()))));
	}

	@Override
	public final Expression decode(StaticDecoders staticDecoders, Expression in, int version, CompatibilityLevel compatibilityLevel) {
		return let(readVarInt(in), length ->
			!nullable ?
				doDecode(staticDecoders, in, version, compatibilityLevel, length) :
				ifEq(length, value(0),
					nullRef(decodeType),
					let(dec(length), len -> doDecode(staticDecoders, in, version, compatibilityLevel, len))));
	}

	protected Expression doDecode(StaticDecoders staticDecoders, Expression in, int version, CompatibilityLevel compatibilityLevel, Expression length) {
		Decoder keyDecoder = keySerializer.defineDecoder(staticDecoders, version, compatibilityLevel);
		Decoder valueDecoder = valueSerializer.defineDecoder(staticDecoders, version, compatibilityLevel);
		return let(createBuilder(length), builder -> sequence(
			iterate(value(0), length,
				i -> putToBuilder(builder, i,
					cast(keyDecoder.decode(in), keyType),
					cast(valueDecoder.decode(in), valueType))),
			build(builder)));
	}

	protected abstract SerializerDef doEnsureNullable(CompatibilityLevel compatibilityLevel);

	protected abstract Expression doIterateMap(Expression collection, BinaryOperator keyValueAction);

	protected abstract Expression createBuilder(Expression length);

	protected abstract Expression putToBuilder(Expression builder, Expression index, Expression key, Expression value);

	protected abstract Expression build(Expression builder);
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy