Для этого я бы предложил реализовать собственный кодек или кодекдекоратор, в зависимости от того, что вы хотите сделать. Если все, что вы хотите сделать, это сохранить последовательность байтов в своем собственном массиве байтов, то создание собственного кодека и подключение его к платформе должно быть довольно простым.
Вот реализация кодека, которая, вероятно, близка к тому, что вы ищете:
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 перегружало бы фреймворк. Это не означает, что вы должны полагаться на все, что фреймворк предлагает по умолчанию. Это просто означает, что вы должны подключить свои собственные расширения.
person
Wilfred Springer
schedule
13.02.2011