Для этого я бы предложил реализовать собственный кодек или CodecDecorator, в зависимости от того, что вы хотите сделать.Если все, что вы хотите сделать, это сохранить последовательность байтов в вашем собственном байтовом массиве, то создание собственного кодека и его подключение к фреймворку должно быть довольно простым.
Вот реализация кодека, которая, вероятно, приближается к тому, что вы ищете:
VariableLengthByteArrayCodec:
package org.codehaus.preon.sample.varlength;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.codehaus.preon.Builder;
import org.codehaus.preon.Codec;
import org.codehaus.preon.CodecDescriptor;
import org.codehaus.preon.DecodingException;
import org.codehaus.preon.Resolver;
import org.codehaus.preon.buffer.BitBuffer;
import org.codehaus.preon.channel.BitChannel;
import org.codehaus.preon.el.Expression;
import nl.flotsam.pecia.Documenter;
import nl.flotsam.pecia.ParaContents;
import nl.flotsam.pecia.SimpleContents;
public class VariableLengthByteArrayCodec implements Codec<byte[]> {
public byte[] decode(BitBuffer buffer, Resolver resolver, Builder builder) throws DecodingException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
boolean cont = true;
while (cont) {
byte b = buffer.readAsByte(8);
bout.write(b);
cont = (b & (1 << 7)) > 0;
}
return bout.toByteArray();
}
public void encode(byte[] value, BitChannel channel, Resolver resolver) throws IOException {
channel.write(value, 0, value.length - 1);
}
public Expression<Integer, Resolver> getSize() {
return null;
}
public CodecDescriptor getCodecDescriptor() {
return new CodecDescriptor() {
public <C extends ParaContents<?>> Documenter<C> summary() {
return new Documenter<C>() {
public void document(C target) {
target.document(reference(Adjective.A, true));
target.text(".");
}
};
}
public <C extends ParaContents<?>> Documenter<C> reference(final Adjective adjective, final boolean startWithCapital) {
return new Documenter<C>() {
public void document(C target) {
target.text(adjective.asTextPreferA(startWithCapital))
.text("variable length encoded byte array.");
}
};
}
public <C extends SimpleContents<?>> Documenter<C> details(String bufferReference) {
return new Documenter<C>() {
public void document(C target) {
target.para()
.text("The number of bytes is determined by the ")
.text("leading bit of the individual bytes; ")
.text("if the first bit of a byte is 1, then ")
.text("more bytes are expted to follow.");
}
};
}
public boolean requiresDedicatedSection() {
return false;
}
public String getTitle() {
assert requiresDedicatedSection();
return null;
}
};
}
public Class<?>[] getTypes() {
return new Class<?>[] { Byte[].class };
}
public Class<?> getType() {
return Byte[].class;
}
}
VariableLengthByteArrayCodecFactory:
package org.codehaus.preon.sample.varlength;
import java.lang.reflect.AnnotatedElement;
import org.codehaus.preon.Codec;
import org.codehaus.preon.CodecFactory;
import org.codehaus.preon.ResolverContext;
public class VariableLengthByteArrayCodecFactory implements CodecFactory {
public <T> Codec<T> create(AnnotatedElement metadata, Class<T> type, ResolverContext context) {
if (metadata != null && metadata.isAnnotationPresent(VarLengthEncoded.class) && type == byte[].class) {
return (Codec<T>) new VariableLengthByteArrayCodec();
} else {
return null;
}
}
}
VarLengthEncoded:
package org.codehaus.preon.sample.varlength;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface VarLengthEncoded {
}
И, наконец, вот как вы его используете:
public static class SomeHolder {
@VarLengthEncoded byte[] value;
public byte[] getValue() {
return value;
}
}
...
Codec<SomeHolder> codec = Codecs.create(SomeHolder.class, new VariableLengthByteArrayCodecFactory());
SomeHolder holder = Codecs.decode(codec, (byte) 0xff, (byte) 0x0f);
assertThat(holder.getValue(), is(not(nullValue())));
assertThat(holder.getValue().length, is(2));
assertThat(holder.getValue()[0], is((byte) 0xff));
assertThat(holder.getValue()[1], is((byte) 0x0f));
Этоможет показаться довольно большим количеством кода, но если вы внимательно проверите, то вы заметите, что большая часть кода на самом деле проверяет, что генерируется правильное описание всякий раз, когда вы будете генерировать документацию для классов с аннотацией @VarLengthEncoded.Если вам вообще не нужна документация, вы можете просто вернуть CodecDescriptor по умолчанию.
Итак, я полагаю, суть этого ответа такова: безусловно, существуют случаи, когда обеспечение реализации в самой Preon перегружало бы фреймворк.Это не значит, что вы должны полагаться на все, что фреймворк может предложить по умолчанию.Это просто означает, что вы должны подключить свои собственные расширения.