parsingdata / metal

A Java library for parsing binary data formats, using declarative descriptions.
Apache License 2.0
18 stars 9 forks source link

Can we benefit from a DelayedValue implementation? #396

Open mvanaken opened 1 year ago

mvanaken commented 1 year ago

There are several ways to produce values in Metal. The implementations of Value in metal are:

The ValueExpression interface uses list semantics, and applies the conversion to every value and creates a CoreValue from it. However, in combination with nth(), only one value is used, so we only need to create this single CoreValue instead.

So the question is: can we delay the creation of CoreValues when we actually need it?

public class DelayedValue<T> implements Value {

    private final T item;
    private final Encoding encoding;
    private final BiFunction<T, Encoding, Value> converter;
    private Value delayedValue;

    public DelayedValue(final T item, final Encoding encoding, final BiFunction<T, Encoding, Value> converter) {
        this.item = item;
        this.encoding = encoding;
        this.converter = converter;
    }

    private void init() {
        if (delayedValue == null) {
            delayedValue = converter.apply(item, encoding);
        }
    }

    @Override
    public Slice slice() {
        init();
        return delayedValue.slice();
    }

    @Override
    public Encoding encoding() {
        return encoding;
    }

    @Override
    public byte[] value() {
        init();
        return delayedValue.value();
    }

    @Override
    public BigInteger length() {
        init();
        return delayedValue.length();
    }

    @Override
    public BigInteger asNumeric() {
        init();
        return delayedValue.asNumeric();
    }

    @Override
    public String asString() {
        init();
        return delayedValue.asString();
    }

    @Override
    public BitSet asBitSet() {
        init();
        return delayedValue.asBitSet();
    }

    @Override
    public String toString() {
        if (delayedValue == null) {
            return "(delayed value)";
        }
        return delayedValue.toString();
    }

    @Override
    public boolean equals(final Object obj) {
        init();
        return Util.notNullAndSameClass(delayedValue, obj)
            && Objects.equals(delayedValue, obj);
    }

    @Override
    public int hashCode() {
        init();
        return Objects.hash(delayedValue);
    }
}
mvanaken commented 1 year ago

@rdvdijk and @Carly-1, this is the implementation of the DelayedValue as discussed last week. See if you can find an example in your codebase that may benefit from this.