All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.permazen.encoding.ObjectArrayEncoding Maven / Gradle / Ivy

The newest version!

/*
 * Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
 */

package io.permazen.encoding;

import com.google.common.base.Preconditions;
import com.google.common.reflect.TypeParameter;
import com.google.common.reflect.TypeToken;

import io.permazen.util.ByteReader;
import io.permazen.util.ByteWriter;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

/**
 * Support superclass for non-null object array encodings.
 *
 * 

* Null values are not supported by this class and there is no default value. * However the array elements can be null. * *

* In the binary encoding, array elements are simply concatenated, with each element preceded by a {@code 0x01} byte * unless encoded array elements never start with {@code 0x00}. After the last array element, a final {@code 0x00} * is then appended. This encoding ensures lexicographic ordering (though there is a subtlety here, which is that when * omitting the {@code 0x01} bytes, we are relying on the fact that for any {@link Encoding} no encoded value can be a * prefix of a another value, because that violates the self-delimiting requirement; as a result, it's not possible * for two concatenated values [B,C] to sort before a single value [A] if A < B). * * @param array element type */ public class ObjectArrayEncoding extends ArrayEncoding { private static final long serialVersionUID = -2337331922923184256L; private static final int END = 0x00; private static final int VALUE = 0x01; private final boolean inlineValue; @SuppressWarnings("serial") public ObjectArrayEncoding(Encoding elementEncoding) { super(elementEncoding, new TypeToken() { }.where(new TypeParameter() { }, elementEncoding.getTypeToken())); Preconditions.checkArgument(!elementEncoding.getTypeToken().isPrimitive(), "illegal primitive element type"); this.inlineValue = !elementEncoding.hasPrefix0x00(); } @Override public E[] read(ByteReader reader) { Preconditions.checkArgument(reader != null); final ArrayList list = new ArrayList<>(); while (true) { final int first = reader.readByte(); if (first == END) break; if (this.inlineValue) reader.unread(); else if (first != VALUE) throw new IllegalArgumentException(String.format("invalid encoding of %s", this)); list.add(this.elementEncoding.read(reader)); } return this.createArray(list); } @Override public void write(ByteWriter writer, E[] array) { Preconditions.checkArgument(writer != null); for (E obj : array) { if (!this.inlineValue) writer.writeByte(VALUE); this.elementEncoding.write(writer, obj); } writer.writeByte(END); } @Override public void skip(ByteReader reader) { Preconditions.checkArgument(reader != null); while (true) { final int first = reader.readByte(); if (first == END) break; if (this.inlineValue) reader.unread(); else if (first != VALUE) throw new IllegalArgumentException(String.format("invalid encoding of %s", this)); this.elementEncoding.skip(reader); } } @Override public boolean hasPrefix0x00() { return true; } @Override public boolean hasPrefix0xff() { return this.inlineValue && this.elementEncoding.hasPrefix0xff(); } // ArrayEncoding @Override protected int getArrayLength(E[] array) { return array.length; } @Override protected E getArrayElement(E[] array, int index) { return array[index]; } @Override @SuppressWarnings("unchecked") protected E[] createArray(List elements) { return elements.toArray((E[])Array.newInstance(this.elementEncoding.getTypeToken().getRawType(), elements.size())); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy