DictEntryEncoder.java
/*
* SPDX-FileCopyrightText: 2023-2025 Lucimber UG
* SPDX-License-Identifier: Apache-2.0
*/
package com.lucimber.dbus.codec.encoder;
import com.lucimber.dbus.type.DBusBasicType;
import com.lucimber.dbus.type.DBusDictEntry;
import com.lucimber.dbus.type.DBusSignature;
import com.lucimber.dbus.type.DBusType;
import com.lucimber.dbus.type.Type;
import com.lucimber.dbus.util.LoggerUtils;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An encoder which encodes a key-value pair to the D-Bus marshalling format using ByteBuffer.
*
* @param <KeyT> The data type of the key.
* @param <ValueT> The data type of the value.
* @see Encoder
* @see DBusDictEntry
*/
public final class DictEntryEncoder<KeyT extends DBusBasicType, ValueT extends DBusType>
implements Encoder<DBusDictEntry<KeyT, ValueT>, ByteBuffer> {
private static final Logger LOGGER = LoggerFactory.getLogger(DictEntryEncoder.class);
private final ByteOrder order;
private final DBusSignature signature;
/**
* Constructs a new instance with mandatory parameters.
*
* @param order The byte order of the produced bytes.
* @param signature The signature of the dictionary entry.
*/
public DictEntryEncoder(ByteOrder order, DBusSignature signature) {
this.order = Objects.requireNonNull(order, "order must not be null");
this.signature = Objects.requireNonNull(signature, "signature must not be null");
}
@Override
public EncoderResult<ByteBuffer> encode(DBusDictEntry<KeyT, ValueT> entry, int offset)
throws EncoderException {
Objects.requireNonNull(entry, "entry must not be null");
try {
int producedBytes = 0;
int padding =
EncoderUtils.calculateAlignmentPadding(Type.DICT_ENTRY.getAlignment(), offset);
producedBytes += padding;
// Encode key
KeyT key = entry.getKey();
int keyOffset = offset + producedBytes;
EncoderResult<ByteBuffer> keyResult = EncoderUtils.encode(key, keyOffset, order);
final ByteBuffer keyBuffer = keyResult.getBuffer();
producedBytes += keyResult.getProducedBytes();
// Encode value
ValueT value = entry.getValue();
int valueOffset = offset + producedBytes;
EncoderResult<ByteBuffer> valueResult = EncoderUtils.encode(value, valueOffset, order);
final ByteBuffer valueBuffer = valueResult.getBuffer();
producedBytes += valueResult.getProducedBytes();
// Assemble final buffer
ByteBuffer buffer = ByteBuffer.allocate(producedBytes).order(order);
for (int i = 0; i < padding; i++) {
buffer.put((byte) 0);
}
buffer.put(keyBuffer);
buffer.put(valueBuffer);
buffer.flip();
EncoderResult<ByteBuffer> result = new EncoderResultImpl<>(producedBytes, buffer);
LOGGER.debug(
LoggerUtils.MARSHALLING,
"DICT_ENTRY: {}; Offset: {}; Padding: {}; Produced bytes: {};",
signature,
offset,
padding,
result.getProducedBytes());
return result;
} catch (Exception ex) {
throw new EncoderException("Could not encode DICT_ENTRY.", ex);
}
}
}