DefaultDecoderFactory.java
/*
* SPDX-FileCopyrightText: 2025 Lucimber UG
* SPDX-License-Identifier: Apache-2.0
*/
package com.lucimber.dbus.codec.decoder;
import com.lucimber.dbus.type.DBusType;
import com.lucimber.dbus.type.Type;
import com.lucimber.dbus.type.TypeCode;
import java.nio.ByteBuffer;
import java.util.EnumMap;
import java.util.Map;
import java.util.Objects;
/**
* Default implementation of DecoderFactory that provides decoders for all standard D-Bus types.
*
* <p>This factory uses a registry-based approach to create decoders, making it easy to extend with
* new types and improving performance by avoiding switch statements.
*/
public final class DefaultDecoderFactory implements DecoderFactory {
private final Map<TypeCode, DecoderCreator> decoderRegistry;
/** Creates a new DefaultDecoderFactory with all standard D-Bus decoders registered. */
public DefaultDecoderFactory() {
this.decoderRegistry = new EnumMap<>(TypeCode.class);
registerStandardDecoders();
}
private void registerStandardDecoders() {
// Basic types
decoderRegistry.put(TypeCode.BOOLEAN, BooleanDecoder::new);
decoderRegistry.put(TypeCode.BYTE, ByteDecoder::new);
decoderRegistry.put(TypeCode.DOUBLE, DoubleDecoder::new);
decoderRegistry.put(TypeCode.INT16, Int16Decoder::new);
decoderRegistry.put(TypeCode.INT32, Int32Decoder::new);
decoderRegistry.put(TypeCode.INT64, Int64Decoder::new);
decoderRegistry.put(TypeCode.UINT16, UInt16Decoder::new);
decoderRegistry.put(TypeCode.UINT32, UInt32Decoder::new);
decoderRegistry.put(TypeCode.UINT64, UInt64Decoder::new);
decoderRegistry.put(TypeCode.STRING, StringDecoder::new);
decoderRegistry.put(TypeCode.OBJECT_PATH, ObjectPathDecoder::new);
decoderRegistry.put(TypeCode.SIGNATURE, SignatureDecoder::new);
decoderRegistry.put(TypeCode.UNIX_FD, UnixFdDecoder::new);
decoderRegistry.put(TypeCode.VARIANT, VariantDecoder::new);
}
@Override
@SuppressWarnings("unchecked")
public Decoder<ByteBuffer, DBusType> createDecoder(TypeCode typeCode) throws DecoderException {
Objects.requireNonNull(typeCode, "typeCode must not be null");
DecoderCreator creator = decoderRegistry.get(typeCode);
if (creator == null) {
throw new DecoderException("No decoder available for type code: " + typeCode);
}
return (Decoder<ByteBuffer, DBusType>) creator.create();
}
@Override
public Decoder<ByteBuffer, DBusType> createDecoder(Type type) throws DecoderException {
Objects.requireNonNull(type, "type must not be null");
TypeCode typeCode = type.getCode();
return createDecoder(typeCode);
}
@Override
public boolean canDecode(TypeCode typeCode) {
return decoderRegistry.containsKey(typeCode);
}
@Override
public boolean canDecode(Type type) {
return type != null && canDecode(type.getCode());
}
/**
* Registers a custom decoder creator for a specific type code.
*
* @param typeCode the D-Bus type code
* @param creator the decoder creator function
*/
public void registerDecoder(TypeCode typeCode, DecoderCreator creator) {
Objects.requireNonNull(typeCode, "typeCode must not be null");
Objects.requireNonNull(creator, "creator must not be null");
decoderRegistry.put(typeCode, creator);
}
/** Functional interface for creating decoders. */
@FunctionalInterface
public interface DecoderCreator {
Decoder<ByteBuffer, ?> create() throws DecoderException;
}
}