package org.jf.dexlib2.dexbacked;
import com.google.common.collect.ImmutableSet;
import org.jf.dexlib2.HiddenApiRestriction;
import org.jf.dexlib2.base.reference.BaseFieldReference;
import org.jf.dexlib2.dexbacked.raw.FieldIdItem;
import org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference;
import org.jf.dexlib2.dexbacked.util.AnnotationsDirectory;
import org.jf.dexlib2.dexbacked.util.EncodedArrayItemIterator;
import org.jf.dexlib2.dexbacked.value.DexBackedEncodedValue;
import org.jf.dexlib2.iface.ClassDef;
import org.jf.dexlib2.iface.Field;
import org.jf.dexlib2.iface.value.EncodedValue;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.EnumSet;
import java.util.Set;
public class DexBackedField extends BaseFieldReference implements Field {
@Nonnull public final DexBackedDexFile dexFile;
@Nonnull public final ClassDef classDef;
public final int accessFlags;
@Nullable public final EncodedValue initialValue;
public final int annotationSetOffset;
public final int fieldIndex;
private final int startOffset;
private final int initialValueOffset;
private final int hiddenApiRestrictions;
private int fieldIdItemOffset;
public DexBackedField(@Nonnull DexBackedDexFile dexFile,
@Nonnull DexReader reader,
@Nonnull DexBackedClassDef classDef,
int previousFieldIndex,
@Nonnull EncodedArrayItemIterator staticInitialValueIterator,
@Nonnull AnnotationsDirectory.AnnotationIterator annotationIterator,
int hiddenApiRestrictions) {
this.dexFile = dexFile;
this.classDef = classDef;
startOffset = reader.getOffset();
int fieldIndexDiff = reader.readLargeUleb128();
this.fieldIndex = fieldIndexDiff + previousFieldIndex;
this.accessFlags = reader.readSmallUleb128();
this.annotationSetOffset = annotationIterator.seekTo(fieldIndex);
initialValueOffset = staticInitialValueIterator.getReaderOffset();
this.initialValue = staticInitialValueIterator.getNextOrNull();
this.hiddenApiRestrictions = hiddenApiRestrictions;
}
public DexBackedField(@Nonnull DexBackedDexFile dexFile,
@Nonnull DexReader reader,
@Nonnull DexBackedClassDef classDef,
int previousFieldIndex,
@Nonnull AnnotationsDirectory.AnnotationIterator annotationIterator,
int hiddenApiRestrictions) {
this.dexFile = dexFile;
this.classDef = classDef;
startOffset = reader.getOffset();
int fieldIndexDiff = reader.readLargeUleb128();
this.fieldIndex = fieldIndexDiff + previousFieldIndex;
this.accessFlags = reader.readSmallUleb128();
this.annotationSetOffset = annotationIterator.seekTo(fieldIndex);
initialValueOffset = 0;
this.initialValue = null;
this.hiddenApiRestrictions = hiddenApiRestrictions;
}
@Nonnull
@Override
public String getName() {
return dexFile.getStringSection().get(
dexFile.getBuffer().readSmallUint(getFieldIdItemOffset() + FieldIdItem.NAME_OFFSET));
}
@Nonnull
@Override
public String getType() {
return dexFile.getTypeSection().get(
dexFile.getBuffer().readUshort(getFieldIdItemOffset() + FieldIdItem.TYPE_OFFSET));
}
@Nonnull @Override public String getDefiningClass() { return classDef.getType(); }
@Override public int getAccessFlags() { return accessFlags; }
@Nullable @Override public EncodedValue getInitialValue() { return initialValue; }
@Nonnull
@Override
public Set<? extends DexBackedAnnotation> getAnnotations() {
return AnnotationsDirectory.getAnnotations(dexFile, annotationSetOffset);
}
@Nonnull
@Override
public Set<HiddenApiRestriction> getHiddenApiRestrictions() {
if (hiddenApiRestrictions == DexBackedClassDef.NO_HIDDEN_API_RESTRICTIONS) {
return ImmutableSet.of();
} else {
return EnumSet.copyOf(HiddenApiRestriction.getAllFlags(hiddenApiRestrictions));
}
}
public static void skipFields(@Nonnull DexReader reader, int count) {
for (int i=0; i<count; i++) {
reader.skipUleb128();
reader.skipUleb128();
}
}
private int getFieldIdItemOffset() {
if (fieldIdItemOffset == 0) {
fieldIdItemOffset = dexFile.getFieldSection().getOffset(fieldIndex);
}
return fieldIdItemOffset;
}
public int getSize() {
int size = 0;
DexReader reader = dexFile.getBuffer().readerAt(startOffset);
reader.readLargeUleb128();
reader.readSmallUleb128();
size += reader.getOffset() - startOffset;
Set<? extends DexBackedAnnotation> annotations = getAnnotations();
if (!annotations.isEmpty()) {
size += 2 * 4;
}
if (initialValueOffset > 0) {
reader.setOffset(initialValueOffset);
if (initialValue != null) {
DexBackedEncodedValue.skipFrom(reader);
size += reader.getOffset() - initialValueOffset;
}
}
DexBackedFieldReference fieldRef = new DexBackedFieldReference(dexFile, fieldIndex);
size += fieldRef.getSize();
return size;
}
}