Implement support in dexlib2 for payload instructions

This commit is contained in:
Ben Gruver 2012-10-26 00:49:31 -07:00
parent 68f69b899f
commit c307c1887d
18 changed files with 926 additions and 16 deletions

View File

@ -63,20 +63,20 @@ public enum Format {
Format3rmi(6), Format3rmi(6),
Format3rms(6), Format3rms(6),
Format51l(10), Format51l(10),
ArrayData(-1, true), ArrayPayload(-1, true),
PackedSwitchData(-1, true), PackedSwitchPayload(-1, true),
SparseSwitchData(-1, true), SparseSwitchPayload(-1, true),
UnresolvedOdexInstruction(-1, false); UnresolvedOdexInstruction(-1);
public final int size; public final int size;
public final boolean variableSizeFormat; public final boolean payloadFormat;
private Format(int size) { private Format(int size) {
this(size, false); this(size, false);
} }
private Format(int size, boolean variableSizeFormat) { private Format(int size, boolean payloadFormat) {
this.size = size; this.size = size;
this.variableSizeFormat = variableSizeFormat; this.payloadFormat = payloadFormat;
} }
} }

View File

@ -283,7 +283,11 @@ public enum Opcode
IPUT_OBJECT_VOLATILE((short)0xfc, "iput-object-volatile", ReferenceType.FIELD, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE), IPUT_OBJECT_VOLATILE((short)0xfc, "iput-object-volatile", ReferenceType.FIELD, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
SGET_OBJECT_VOLATILE((short)0xfd, "sget-object-volatile", ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), SGET_OBJECT_VOLATILE((short)0xfd, "sget-object-volatile", ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER),
SPUT_OBJECT_VOLATILE((short)0xfe, "sput-object-volatile", ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE); SPUT_OBJECT_VOLATILE((short)0xfe, "sput-object-volatile", ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE),
PACKED_SWITCH_PAYLOAD((short)0x100, "packed-switch-payload", ReferenceType.NONE, Format.PackedSwitchPayload, 0),
SPARSE_SWITCH_PAYLOAD((short)0x200, "sparse-switch-payload", ReferenceType.NONE, Format.SparseSwitchPayload, 0),
ARRAY_PAYLOAD((short)0x300, "array-payload", ReferenceType.NONE, Format.ArrayPayload, 0);
private static final Opcode[] opcodesByValue; private static final Opcode[] opcodesByValue;
private static final HashMap<Integer, Opcode> opcodesByName; private static final HashMap<Integer, Opcode> opcodesByName;
@ -316,6 +320,7 @@ public enum Opcode
opcodesByName = new HashMap<Integer, Opcode>(); opcodesByName = new HashMap<Integer, Opcode>();
for (Opcode opcode: Opcode.values()) { for (Opcode opcode: Opcode.values()) {
if (!opcode.format.payloadFormat) {
//INVOKE_DIRECT_EMPTY was changed to INVOKE_OBJECT_INIT_RANGE in ICS //INVOKE_DIRECT_EMPTY was changed to INVOKE_OBJECT_INIT_RANGE in ICS
if (opcode != INVOKE_DIRECT_EMPTY) { if (opcode != INVOKE_DIRECT_EMPTY) {
opcodesByValue[opcode.value] = opcode; opcodesByValue[opcode.value] = opcode;
@ -323,14 +328,24 @@ public enum Opcode
} }
} }
} }
}
public static Opcode getOpcodeByName(String opcodeName) { public static Opcode getOpcodeByName(String opcodeName) {
return opcodesByName.get(opcodeName.toLowerCase().hashCode()); return opcodesByName.get(opcodeName.toLowerCase().hashCode());
} }
public static Opcode getOpcodeByValue(int opcodeValue) { public static Opcode getOpcodeByValue(int opcodeValue) {
switch (opcodeValue) {
case 0x100:
return SPARSE_SWITCH_PAYLOAD;
case 0x200:
return PACKED_SWITCH_PAYLOAD;
case 0x300:
return ARRAY_PAYLOAD;
default:
return opcodesByValue[opcodeValue]; return opcodesByValue[opcodeValue];
} }
}
private static void removeOpcodes(Opcode... toRemove) { private static void removeOpcodes(Opcode... toRemove) {
for (Opcode opcode: toRemove) { for (Opcode opcode: toRemove) {

View File

@ -0,0 +1,120 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.dexbacked.instruction;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.dexbacked.DexBuffer;
import org.jf.dexlib2.dexbacked.util.FixedSizeList;
import org.jf.dexlib2.iface.instruction.formats.ArrayPayload;
import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull;
import java.util.List;
public class DexBackedArrayPayload implements ArrayPayload {
public static final Opcode OPCODE = Opcode.ARRAY_PAYLOAD;
@Nonnull public final DexBuffer dexBuf;
private final int instructionOffset;
public final int elementWidth;
public final int elementCount;
private static final int ELEMENT_WIDTH_OFFSET = 2;
private static final int ELEMENT_COUNT_OFFSET = 4;
private static final int ELEMENTS_OFFSET = 8;
public DexBackedArrayPayload(DexBuffer dexBuf,
int instructionOffset) {
this.dexBuf = dexBuf;
this.instructionOffset = instructionOffset;
this.elementWidth = dexBuf.readUshort(instructionOffset + ELEMENT_WIDTH_OFFSET);
this.elementCount = dexBuf.readSmallUint(instructionOffset + ELEMENT_COUNT_OFFSET);
}
@Override public int getElementWidth() { return elementWidth; }
@Nonnull
@Override
public List<Number> getArrayElements() {
final int elementsStart = instructionOffset + ELEMENTS_OFFSET;
abstract class ReturnedList extends FixedSizeList<Number> {
@Override public int size() { return elementCount; }
}
switch (elementWidth) {
case 1:
return new ReturnedList() {
@Nonnull
@Override
public Number readItem(int index) {
return dexBuf.readByte(elementsStart + index);
}
};
case 2:
return new ReturnedList() {
@Nonnull
@Override
public Number readItem(int index) {
return dexBuf.readShort(elementsStart + index*2);
}
};
case 4:
return new ReturnedList() {
@Nonnull
@Override
public Number readItem(int index) {
return dexBuf.readInt(elementsStart + index*4);
}
};
case 8:
return new ReturnedList() {
@Nonnull
@Override
public Number readItem(int index) {
return dexBuf.readLong(elementsStart + index*8);
}
};
default:
throw new ExceptionWithContext("Invalid element width: %d", elementWidth);
}
}
@Override
public int getCodeUnits() {
return 4 + (elementWidth*elementCount + 1) / 2;
}
@Override public Opcode getOpcode() { return OPCODE; }
}

View File

@ -45,6 +45,10 @@ public abstract class DexBackedInstruction {
@Nonnull @Nonnull
public static Instruction readFrom(@Nonnull DexReader reader) { public static Instruction readFrom(@Nonnull DexReader reader) {
int opcodeValue = reader.readUbyte(); int opcodeValue = reader.readUbyte();
if (opcodeValue == 0) {
reader.moveRelative(-1);
opcodeValue = reader.readUshort();
}
Opcode opcode = Opcode.getOpcodeByValue(opcodeValue); Opcode opcode = Opcode.getOpcodeByValue(opcodeValue);
@ -101,6 +105,13 @@ public abstract class DexBackedInstruction {
return instruction3rc(opcode, reader); return instruction3rc(opcode, reader);
case Format51l: case Format51l:
return instruction51l(opcode, reader); return instruction51l(opcode, reader);
case PackedSwitchPayload:
return packedSwitchPayload(reader);
case SparseSwitchPayload:
return sparseSwitchPayload(reader);
case ArrayPayload:
return arrayPayload(reader);
//TODO: temporary, until we get all instructions implemented
default: default:
throw new ExceptionWithContext("Unexpected opcode format: %s", opcode.format.toString()); throw new ExceptionWithContext("Unexpected opcode format: %s", opcode.format.toString());
} }
@ -308,4 +319,33 @@ public abstract class DexBackedInstruction {
long literal = reader.readLong(); long literal = reader.readLong();
return new ImmutableInstruction51l(opcode, registerA, literal); return new ImmutableInstruction51l(opcode, registerA, literal);
} }
@Nonnull
private static DexBackedPackedSwitchPayload packedSwitchPayload(@Nonnull DexReader reader) {
// the reader is currently positioned after the 2-byte "opcode"
int instructionStartOffset = reader.getOffset() - 2;
DexBackedPackedSwitchPayload instruction =
new DexBackedPackedSwitchPayload(reader.getDexBuffer(), instructionStartOffset);
reader.moveRelative(instruction.getCodeUnits() * 2);
return instruction;
}
@Nonnull
private static DexBackedSparseSwitchPayload sparseSwitchPayload(@Nonnull DexReader reader) {
// the reader is currently positioned after the 2-byte "opcode"
int instructionStartOffset = reader.getOffset() - 2;
DexBackedSparseSwitchPayload instruction =
new DexBackedSparseSwitchPayload(reader.getDexBuffer(), instructionStartOffset);
reader.moveRelative(instruction.getCodeUnits() * 2);
return instruction;
}
@Nonnull
private static DexBackedArrayPayload arrayPayload(@Nonnull DexReader reader) {
// the reader is currently positioned after the 2-byte "opcode"
int instructionStartOffset = reader.getOffset() - 2;
DexBackedArrayPayload instruction = new DexBackedArrayPayload(reader.getDexBuffer(), instructionStartOffset);
reader.moveRelative(instruction.getCodeUnits() * 2);
return instruction;
}
} }

View File

@ -0,0 +1,90 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.dexbacked.instruction;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.dexbacked.DexBuffer;
import org.jf.dexlib2.dexbacked.util.FixedSizeList;
import org.jf.dexlib2.iface.instruction.SwitchElement;
import org.jf.dexlib2.iface.instruction.formats.PackedSwitchPayload;
import javax.annotation.Nonnull;
import java.util.List;
public class DexBackedPackedSwitchPayload implements PackedSwitchPayload {
public static final Opcode OPCODE = Opcode.PACKED_SWITCH_PAYLOAD;
@Nonnull public final DexBuffer dexBuf;
private final int instructionOffset;
public final int elementCount;
private static final int ELEMENT_COUNT_OFFSET = 2;
private static final int FIRST_KEY_OFFSET = 4;
private static final int TARGETS_OFFSET = 8;
public DexBackedPackedSwitchPayload(@Nonnull DexBuffer dexBuf,
int instructionOffset) {
this.dexBuf = dexBuf;
this.instructionOffset = instructionOffset;
this.elementCount = dexBuf.readByte(instructionOffset + ELEMENT_COUNT_OFFSET);
}
@Nonnull
@Override
public List<? extends SwitchElement> getSwitchElements() {
final int firstKey = dexBuf.readInt(instructionOffset + FIRST_KEY_OFFSET);
return new FixedSizeList<SwitchElement>() {
@Nonnull
@Override
public SwitchElement readItem(final int index) {
return new SwitchElement() {
@Override
public int getKey() {
return firstKey + index;
}
@Override
public int getOffset() {
return dexBuf.readInt(instructionOffset + TARGETS_OFFSET + index*4);
}
};
}
@Override public int size() { return elementCount; }
};
}
@Override public int getCodeUnits() { return 4 + elementCount*2; }
@Override public Opcode getOpcode() { return OPCODE; }
}

View File

@ -0,0 +1,88 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.dexbacked.instruction;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.dexbacked.DexBuffer;
import org.jf.dexlib2.dexbacked.util.FixedSizeList;
import org.jf.dexlib2.iface.instruction.SwitchElement;
import org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload;
import javax.annotation.Nonnull;
import java.util.List;
public class DexBackedSparseSwitchPayload implements SparseSwitchPayload {
public static final Opcode OPCODE = Opcode.SPARSE_SWITCH_PAYLOAD;
@Nonnull public final DexBuffer dexBuf;
private final int instructionOffset;
public final int elementCount;
private static final int ELEMENT_COUNT_OFFSET = 2;
private static final int KEYS_OFFSET = 4;
public DexBackedSparseSwitchPayload(@Nonnull DexBuffer dexBuf,
int instructionOffset) {
this.dexBuf = dexBuf;
this.instructionOffset = instructionOffset;
this.elementCount = dexBuf.readUshort(instructionOffset + ELEMENT_COUNT_OFFSET);
}
@Nonnull
@Override
public List<? extends SwitchElement> getSwitchElements() {
return new FixedSizeList<SwitchElement>() {
@Nonnull
@Override
public SwitchElement readItem(final int index) {
return new SwitchElement() {
@Override
public int getKey() {
return dexBuf.readInt(instructionOffset + KEYS_OFFSET + index*4);
}
@Override
public int getOffset() {
return dexBuf.readInt(instructionOffset + KEYS_OFFSET + elementCount*4 + index*4);
}
};
}
@Override public int size() { return elementCount; }
};
}
@Override public int getCodeUnits() { return 2 + elementCount*4; }
@Override public Opcode getOpcode() { return OPCODE; }
}

View File

@ -35,4 +35,5 @@ import org.jf.dexlib2.Opcode;
public interface Instruction { public interface Instruction {
Opcode getOpcode(); Opcode getOpcode();
int getCodeUnits();
} }

View File

@ -0,0 +1,38 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.iface.instruction;
/**
* Empty marker interface for the switch/array payload instructions
*/
public interface PayloadInstruction extends Instruction {
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.iface.instruction;
public interface SwitchElement {
public int getKey();
public int getOffset();
}

View File

@ -0,0 +1,39 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.iface.instruction;
import javax.annotation.Nonnull;
import java.util.List;
public interface SwitchPayload extends PayloadInstruction {
@Nonnull List<? extends SwitchElement> getSwitchElements();
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.iface.instruction.formats;
import org.jf.dexlib2.iface.instruction.PayloadInstruction;
import javax.annotation.Nonnull;
import java.util.List;
public interface ArrayPayload extends PayloadInstruction {
public int getElementWidth();
@Nonnull public List<Number> getArrayElements();
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.iface.instruction.formats;
import org.jf.dexlib2.iface.instruction.SwitchPayload;
public interface PackedSwitchPayload extends SwitchPayload {
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.iface.instruction.formats;
import org.jf.dexlib2.iface.instruction.SwitchPayload;
public interface SparseSwitchPayload extends SwitchPayload {
}

View File

@ -0,0 +1,81 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.immutable.instruction;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import org.jf.dexlib2.Format;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.iface.instruction.formats.ArrayPayload;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class ImmutableArrayPayload extends ImmutableInstruction implements ArrayPayload {
public static final Opcode OPCODE = Opcode.ARRAY_PAYLOAD;
public final int elementWidth;
@Nonnull public final ImmutableList<Number> arrayElements;
public ImmutableArrayPayload(int elementWidth,
@Nullable List<Number> arrayElements) {
super(OPCODE);
this.elementWidth = elementWidth;
this.arrayElements = arrayElements==null ? ImmutableList.<Number>of() : ImmutableList.copyOf(arrayElements);
}
public ImmutableArrayPayload(int elementWidth,
@Nullable ImmutableList<Number> arrayElements) {
super(OPCODE);
//TODO: need to ensure this is a valid width (1, 2, 4, 8)
this.elementWidth = elementWidth;
//TODO: need to validate the elements fit within the width
this.arrayElements = Objects.firstNonNull(arrayElements, ImmutableList.<Number>of());
}
@Nonnull
public static ImmutableArrayPayload of(ArrayPayload instruction) {
if (instruction instanceof ImmutableArrayPayload) {
return (ImmutableArrayPayload)instruction;
}
return new ImmutableArrayPayload(
instruction.getElementWidth(),
instruction.getArrayElements());
}
@Override public int getElementWidth() { return elementWidth; }
@Nonnull @Override public List<Number> getArrayElements() { return arrayElements; }
@Override public int getCodeUnits() { return 4 + (elementWidth * arrayElements.size() + 1) / 2; }
@Override public Format getFormat() { return OPCODE.format; }
}

View File

@ -43,7 +43,7 @@ import javax.annotation.Nonnull;
import java.util.List; import java.util.List;
public abstract class ImmutableInstruction implements Instruction { public abstract class ImmutableInstruction implements Instruction {
public final Opcode opcode; @Nonnull public final Opcode opcode;
protected ImmutableInstruction(@Nonnull Opcode opcode) { protected ImmutableInstruction(@Nonnull Opcode opcode) {
this.opcode = opcode; this.opcode = opcode;
@ -51,6 +51,7 @@ public abstract class ImmutableInstruction implements Instruction {
Preconditions.checkFormat(opcode, getFormat()); Preconditions.checkFormat(opcode, getFormat());
} }
@Nonnull
public static ImmutableInstruction of(Instruction instruction) { public static ImmutableInstruction of(Instruction instruction) {
if (instruction instanceof ImmutableInstruction) { if (instruction instanceof ImmutableInstruction) {
return (ImmutableInstruction)instruction; return (ImmutableInstruction)instruction;
@ -107,10 +108,17 @@ public abstract class ImmutableInstruction implements Instruction {
return ImmutableInstruction3rc.of((Instruction3rc)instruction); return ImmutableInstruction3rc.of((Instruction3rc)instruction);
case Format51l: case Format51l:
return ImmutableInstruction51l.of((Instruction51l)instruction); return ImmutableInstruction51l.of((Instruction51l)instruction);
} case PackedSwitchPayload:
return ImmutablePackedSwitchPayload.of((PackedSwitchPayload) instruction);
case SparseSwitchPayload:
return ImmutableSparseSwitchPayload.of((SparseSwitchPayload) instruction);
case ArrayPayload:
return ImmutableArrayPayload.of((ArrayPayload) instruction);
//TODO: temporary, until we get all instructions implemented //TODO: temporary, until we get all instructions implemented
default:
throw new RuntimeException("Unexpected instruction type"); throw new RuntimeException("Unexpected instruction type");
} }
}
public Opcode getOpcode() { public Opcode getOpcode() {
return opcode; return opcode;
@ -118,6 +126,10 @@ public abstract class ImmutableInstruction implements Instruction {
public abstract Format getFormat(); public abstract Format getFormat();
public int getCodeUnits() {
return getFormat().size * 2;
}
@Nonnull @Nonnull
public static ImmutableList<ImmutableInstruction> immutableListOf(List<? extends Instruction> list) { public static ImmutableList<ImmutableInstruction> immutableListOf(List<? extends Instruction> list) {
return CONVERTER.convert(list); return CONVERTER.convert(list);
@ -130,6 +142,7 @@ public abstract class ImmutableInstruction implements Instruction {
return item instanceof ImmutableInstruction; return item instanceof ImmutableInstruction;
} }
@Nonnull
@Override @Override
protected ImmutableInstruction makeImmutable(Instruction item) { protected ImmutableInstruction makeImmutable(Instruction item) {
return ImmutableInstruction.of(item); return ImmutableInstruction.of(item);

View File

@ -0,0 +1,75 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.immutable.instruction;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import org.jf.dexlib2.Format;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.iface.instruction.SwitchElement;
import org.jf.dexlib2.iface.instruction.formats.PackedSwitchPayload;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class ImmutablePackedSwitchPayload extends ImmutableInstruction implements PackedSwitchPayload {
public static final Opcode OPCODE = Opcode.PACKED_SWITCH_PAYLOAD;
@Nonnull public final ImmutableList<? extends ImmutableSwitchElement> switchElements;
public ImmutablePackedSwitchPayload(@Nullable List<? extends SwitchElement> switchElements) {
super(OPCODE);
//TODO: need to validate that the keys are sequential
this.switchElements = ImmutableSwitchElement.immutableListOf(switchElements);
}
public ImmutablePackedSwitchPayload(
@Nullable ImmutableList<? extends ImmutableSwitchElement> switchElements) {
super(OPCODE);
this.switchElements = Objects.firstNonNull(switchElements, ImmutableList.<ImmutableSwitchElement>of());
}
@Nonnull
public static ImmutablePackedSwitchPayload of(PackedSwitchPayload instruction) {
if (instruction instanceof ImmutablePackedSwitchPayload) {
return (ImmutablePackedSwitchPayload)instruction;
}
return new ImmutablePackedSwitchPayload(
instruction.getSwitchElements());
}
@Nonnull @Override public List<? extends SwitchElement> getSwitchElements() { return switchElements; }
@Override public int getCodeUnits() { return 4 + switchElements.size() * 2; }
@Override public Format getFormat() { return OPCODE.format; }
}

View File

@ -0,0 +1,75 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.immutable.instruction;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import org.jf.dexlib2.Format;
import org.jf.dexlib2.Opcode;
import org.jf.dexlib2.iface.instruction.SwitchElement;
import org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload;
import org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public class ImmutableSparseSwitchPayload extends ImmutableInstruction implements SparseSwitchPayload {
public static final Opcode OPCODE = Opcode.SPARSE_SWITCH_PAYLOAD;
@Nonnull public final ImmutableList<? extends ImmutableSwitchElement> switchElements;
public ImmutableSparseSwitchPayload(@Nullable List<? extends SwitchElement> switchElements) {
super(OPCODE);
this.switchElements = ImmutableSwitchElement.immutableListOf(switchElements);
}
public ImmutableSparseSwitchPayload(
@Nullable ImmutableList<? extends ImmutableSwitchElement> switchElements) {
super(OPCODE);
this.switchElements = Objects.firstNonNull(switchElements, ImmutableList.<ImmutableSwitchElement>of());
}
@Nonnull
public static ImmutableSparseSwitchPayload of(SparseSwitchPayload instruction) {
if (instruction instanceof ImmutableSparseSwitchPayload) {
return (ImmutableSparseSwitchPayload)instruction;
}
return new ImmutableSparseSwitchPayload(
instruction.getSwitchElements());
}
@Nonnull @Override public List<? extends SwitchElement> getSwitchElements() { return switchElements; }
@Override public int getCodeUnits() { return 2 + switchElements.size() * 4; }
@Override public Format getFormat() { return OPCODE.format; }
}

View File

@ -0,0 +1,82 @@
/*
* Copyright 2012, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jf.dexlib2.immutable.instruction;
import com.google.common.collect.ImmutableList;
import org.jf.dexlib2.iface.instruction.SwitchElement;
import org.jf.util.ImmutableListConverter;
import javax.annotation.Nonnull;
import java.util.List;
public class ImmutableSwitchElement implements SwitchElement {
public final int key;
public final int offset;
public ImmutableSwitchElement(int key,
int offset) {
this.key = key;
this.offset = offset;
}
@Nonnull
public static ImmutableSwitchElement of(SwitchElement switchElement) {
if (switchElement instanceof ImmutableSwitchElement) {
return (ImmutableSwitchElement)switchElement;
}
return new ImmutableSwitchElement(
switchElement.getKey(),
switchElement.getOffset());
}
@Override public int getKey() { return key; }
@Override public int getOffset() { return offset; }
@Nonnull
public static ImmutableList<ImmutableSwitchElement> immutableListOf(List<? extends SwitchElement> list) {
return CONVERTER.convert(list);
}
private static final ImmutableListConverter<ImmutableSwitchElement, SwitchElement> CONVERTER =
new ImmutableListConverter<ImmutableSwitchElement, SwitchElement>() {
@Override
protected boolean isImmutable(SwitchElement item) {
return item instanceof ImmutableSwitchElement;
}
@Nonnull
@Override
protected ImmutableSwitchElement makeImmutable(SwitchElement item) {
return ImmutableSwitchElement.of(item);
}
};
}