diff --git a/core/src/main/java/org/elasticsearch/cluster/node/DiscoveryNode.java b/core/src/main/java/org/elasticsearch/cluster/node/DiscoveryNode.java index 0e8435d0f8e..caafb82c657 100644 --- a/core/src/main/java/org/elasticsearch/cluster/node/DiscoveryNode.java +++ b/core/src/main/java/org/elasticsearch/cluster/node/DiscoveryNode.java @@ -238,11 +238,7 @@ public class DiscoveryNode implements Writeable, ToXContent { int rolesSize = in.readVInt(); this.roles = EnumSet.noneOf(Role.class); for (int i = 0; i < rolesSize; i++) { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= Role.values().length) { - throw new IOException("Unknown Role ordinal [" + ordinal + "]"); - } - this.roles.add(Role.values()[ordinal]); + this.roles.add(in.readEnum(Role.class)); } this.version = Version.readVersion(in); } @@ -262,7 +258,7 @@ public class DiscoveryNode implements Writeable, ToXContent { } out.writeVInt(roles.size()); for (Role role : roles) { - out.writeVInt(role.ordinal()); + out.writeEnum(role); } Version.writeVersion(version, out); } diff --git a/core/src/main/java/org/elasticsearch/common/geo/ShapeRelation.java b/core/src/main/java/org/elasticsearch/common/geo/ShapeRelation.java index e9966834a01..e83e18ce432 100644 --- a/core/src/main/java/org/elasticsearch/common/geo/ShapeRelation.java +++ b/core/src/main/java/org/elasticsearch/common/geo/ShapeRelation.java @@ -44,16 +44,12 @@ public enum ShapeRelation implements Writeable { } public static ShapeRelation readFromStream(StreamInput in) throws IOException { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= values().length) { - throw new IOException("Unknown ShapeRelation ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(ShapeRelation.class); } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(ordinal()); + out.writeEnum(this); } public static ShapeRelation getRelationByName(String name) { diff --git a/core/src/main/java/org/elasticsearch/common/geo/SpatialStrategy.java b/core/src/main/java/org/elasticsearch/common/geo/SpatialStrategy.java index acac5fd6690..0b4f640fd28 100644 --- a/core/src/main/java/org/elasticsearch/common/geo/SpatialStrategy.java +++ b/core/src/main/java/org/elasticsearch/common/geo/SpatialStrategy.java @@ -40,16 +40,12 @@ public enum SpatialStrategy implements Writeable { } public static SpatialStrategy readFromStream(StreamInput in) throws IOException { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= values().length) { - throw new IOException("Unknown SpatialStrategy ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(SpatialStrategy.class); } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(ordinal()); + out.writeEnum(this); } public static SpatialStrategy fromString(String strategyName) { diff --git a/core/src/main/java/org/elasticsearch/common/io/stream/StreamInput.java b/core/src/main/java/org/elasticsearch/common/io/stream/StreamInput.java index 0efb99a1fab..4681af3392e 100644 --- a/core/src/main/java/org/elasticsearch/common/io/stream/StreamInput.java +++ b/core/src/main/java/org/elasticsearch/common/io/stream/StreamInput.java @@ -901,6 +901,18 @@ public abstract class StreamInput extends InputStream { return builder; } + /** + * Reads an enum with type E that was serialized based on the value of it's ordinal + */ + public > E readEnum(Class enumClass) throws IOException { + int ordinal = readVInt(); + E[] values = enumClass.getEnumConstants(); + if (ordinal < 0 || ordinal >= values.length) { + throw new IOException("Unknown " + enumClass.getSimpleName() + " ordinal [" + ordinal + "]"); + } + return values[ordinal]; + } + public static StreamInput wrap(byte[] bytes) { return wrap(bytes, 0, bytes.length); } diff --git a/core/src/main/java/org/elasticsearch/common/io/stream/StreamOutput.java b/core/src/main/java/org/elasticsearch/common/io/stream/StreamOutput.java index 4d57e7c1b88..5816a9fd469 100644 --- a/core/src/main/java/org/elasticsearch/common/io/stream/StreamOutput.java +++ b/core/src/main/java/org/elasticsearch/common/io/stream/StreamOutput.java @@ -936,4 +936,11 @@ public abstract class StreamOutput extends OutputStream { } } + /** + * Writes an enum with type E that by serialized it based on it's ordinal value + */ + public > void writeEnum(E enumValue) throws IOException { + writeVInt(enumValue.ordinal()); + } + } diff --git a/core/src/main/java/org/elasticsearch/common/lucene/search/function/CombineFunction.java b/core/src/main/java/org/elasticsearch/common/lucene/search/function/CombineFunction.java index e8bd2887998..90d110c3804 100644 --- a/core/src/main/java/org/elasticsearch/common/lucene/search/function/CombineFunction.java +++ b/core/src/main/java/org/elasticsearch/common/lucene/search/function/CombineFunction.java @@ -143,15 +143,11 @@ public enum CombineFunction implements Writeable { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(this.ordinal()); + out.writeEnum(this); } public static CombineFunction readFromStream(StreamInput in) throws IOException { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= values().length) { - throw new IOException("Unknown CombineFunction ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(CombineFunction.class); } public static CombineFunction fromString(String combineFunction) { diff --git a/core/src/main/java/org/elasticsearch/common/lucene/search/function/FieldValueFactorFunction.java b/core/src/main/java/org/elasticsearch/common/lucene/search/function/FieldValueFactorFunction.java index e225df040ab..1978c0acf0d 100644 --- a/core/src/main/java/org/elasticsearch/common/lucene/search/function/FieldValueFactorFunction.java +++ b/core/src/main/java/org/elasticsearch/common/lucene/search/function/FieldValueFactorFunction.java @@ -191,15 +191,11 @@ public class FieldValueFactorFunction extends ScoreFunction { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(this.ordinal()); + out.writeEnum(this); } public static Modifier readFromStream(StreamInput in) throws IOException { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= values().length) { - throw new IOException("Unknown Modifier ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(Modifier.class); } @Override diff --git a/core/src/main/java/org/elasticsearch/common/lucene/search/function/FiltersFunctionScoreQuery.java b/core/src/main/java/org/elasticsearch/common/lucene/search/function/FiltersFunctionScoreQuery.java index abf145406c5..2f2a70537c0 100644 --- a/core/src/main/java/org/elasticsearch/common/lucene/search/function/FiltersFunctionScoreQuery.java +++ b/core/src/main/java/org/elasticsearch/common/lucene/search/function/FiltersFunctionScoreQuery.java @@ -81,15 +81,11 @@ public class FiltersFunctionScoreQuery extends Query { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(this.ordinal()); + out.writeEnum(this); } public static ScoreMode readFromStream(StreamInput in) throws IOException { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= values().length) { - throw new IOException("Unknown ScoreMode ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(ScoreMode.class); } public static ScoreMode fromString(String scoreMode) { diff --git a/core/src/main/java/org/elasticsearch/index/VersionType.java b/core/src/main/java/org/elasticsearch/index/VersionType.java index fcbd6690a38..c5094ea185d 100644 --- a/core/src/main/java/org/elasticsearch/index/VersionType.java +++ b/core/src/main/java/org/elasticsearch/index/VersionType.java @@ -364,13 +364,11 @@ public enum VersionType implements Writeable { } public static VersionType readFromStream(StreamInput in) throws IOException { - int ordinal = in.readVInt(); - assert (ordinal == 0 || ordinal == 1 || ordinal == 2 || ordinal == 3); - return VersionType.values()[ordinal]; + return in.readEnum(VersionType.class); } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(ordinal()); + out.writeEnum(this); } } diff --git a/core/src/main/java/org/elasticsearch/index/query/Operator.java b/core/src/main/java/org/elasticsearch/index/query/Operator.java index 7972dbb49ad..de88abebad3 100644 --- a/core/src/main/java/org/elasticsearch/index/query/Operator.java +++ b/core/src/main/java/org/elasticsearch/index/query/Operator.java @@ -54,16 +54,12 @@ public enum Operator implements Writeable { } public static Operator readFromStream(StreamInput in) throws IOException { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= values().length) { - throw new IOException("Unknown Operator ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(Operator.class); } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(this.ordinal()); + out.writeEnum(this); } public static Operator fromString(String op) { diff --git a/core/src/main/java/org/elasticsearch/search/MultiValueMode.java b/core/src/main/java/org/elasticsearch/search/MultiValueMode.java index 2d6fd8a2b60..231bc8bf3c0 100644 --- a/core/src/main/java/org/elasticsearch/search/MultiValueMode.java +++ b/core/src/main/java/org/elasticsearch/search/MultiValueMode.java @@ -948,14 +948,10 @@ public enum MultiValueMode implements Writeable { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(this.ordinal()); + out.writeEnum(this); } public static MultiValueMode readMultiValueModeFrom(StreamInput in) throws IOException { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= values().length) { - throw new IOException("Unknown MultiValueMode ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(MultiValueMode.class); } } diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/Aggregator.java b/core/src/main/java/org/elasticsearch/search/aggregations/Aggregator.java index 44adb33c01b..41a0fa6dd30 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/Aggregator.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/Aggregator.java @@ -139,16 +139,12 @@ public abstract class Aggregator extends BucketCollector implements Releasable { } public static SubAggCollectionMode readFromStream(StreamInput in) throws IOException { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= values().length) { - throw new IOException("Unknown SubAggCollectionMode ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(SubAggCollectionMode.class); } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(ordinal()); + out.writeEnum(this); } } } diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentilesMethod.java b/core/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentilesMethod.java index b10880a13c0..3b8085793dc 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentilesMethod.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentilesMethod.java @@ -53,20 +53,16 @@ public enum PercentilesMethod implements Writeable { } public static PercentilesMethod readFromStream(StreamInput in) throws IOException { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= values().length) { - throw new IOException("Unknown PercentilesMethod ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(PercentilesMethod.class); } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(ordinal()); + out.writeEnum(this); } @Override public String toString() { return parseField.getPreferredName(); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/elasticsearch/search/fetch/subphase/highlight/HighlightBuilder.java b/core/src/main/java/org/elasticsearch/search/fetch/subphase/highlight/HighlightBuilder.java index c7c9c547b51..5e49aa7395d 100644 --- a/core/src/main/java/org/elasticsearch/search/fetch/subphase/highlight/HighlightBuilder.java +++ b/core/src/main/java/org/elasticsearch/search/fetch/subphase/highlight/HighlightBuilder.java @@ -504,16 +504,12 @@ public class HighlightBuilder extends AbstractHighlighterBuilder= values().length) { - throw new IOException("Unknown Order ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(Order.class); } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(this.ordinal()); + out.writeEnum(this); } public static Order fromString(String order) { @@ -533,16 +529,12 @@ public class HighlightBuilder extends AbstractHighlighterBuilder= values().length) { - throw new IOException("Unknown BoundaryScannerType ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(BoundaryScannerType.class); } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(this.ordinal()); + out.writeEnum(this); } public static BoundaryScannerType fromString(String boundaryScannerType) { diff --git a/core/src/main/java/org/elasticsearch/search/rescore/QueryRescoreMode.java b/core/src/main/java/org/elasticsearch/search/rescore/QueryRescoreMode.java index 70718b56c0c..51db82652fc 100644 --- a/core/src/main/java/org/elasticsearch/search/rescore/QueryRescoreMode.java +++ b/core/src/main/java/org/elasticsearch/search/rescore/QueryRescoreMode.java @@ -86,16 +86,12 @@ public enum QueryRescoreMode implements Writeable { public abstract float combine(float primary, float secondary); public static QueryRescoreMode readFromStream(StreamInput in) throws IOException { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= values().length) { - throw new IOException("Unknown ScoreMode ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(QueryRescoreMode.class); } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(this.ordinal()); + out.writeEnum(this); } public static QueryRescoreMode fromString(String scoreMode) { @@ -111,4 +107,4 @@ public enum QueryRescoreMode implements Writeable { public String toString() { return name().toLowerCase(Locale.ROOT); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/elasticsearch/search/sort/ScriptSortBuilder.java b/core/src/main/java/org/elasticsearch/search/sort/ScriptSortBuilder.java index 2901e05f051..b136dd77989 100644 --- a/core/src/main/java/org/elasticsearch/search/sort/ScriptSortBuilder.java +++ b/core/src/main/java/org/elasticsearch/search/sort/ScriptSortBuilder.java @@ -350,18 +350,14 @@ public class ScriptSortBuilder extends SortBuilder { @Override public void writeTo(final StreamOutput out) throws IOException { - out.writeVInt(ordinal()); + out.writeEnum(this); } /** * Read from a stream. */ static ScriptSortType readFromStream(final StreamInput in) throws IOException { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= values().length) { - throw new IOException("Unknown ScriptSortType ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(ScriptSortType.class); } public static ScriptSortType fromString(final String str) { diff --git a/core/src/main/java/org/elasticsearch/search/sort/SortMode.java b/core/src/main/java/org/elasticsearch/search/sort/SortMode.java index 21495798a89..07b5bfa98c2 100644 --- a/core/src/main/java/org/elasticsearch/search/sort/SortMode.java +++ b/core/src/main/java/org/elasticsearch/search/sort/SortMode.java @@ -52,15 +52,11 @@ public enum SortMode implements Writeable { @Override public void writeTo(final StreamOutput out) throws IOException { - out.writeVInt(ordinal()); + out.writeEnum(this); } public static SortMode readFromStream(StreamInput in) throws IOException { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= values().length) { - throw new IOException("Unknown SortMode ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(SortMode.class); } public static SortMode fromString(final String str) { @@ -85,4 +81,4 @@ public enum SortMode implements Writeable { public String toString() { return name().toLowerCase(Locale.ROOT); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/elasticsearch/search/sort/SortOrder.java b/core/src/main/java/org/elasticsearch/search/sort/SortOrder.java index cd0a3bb6d46..fbcb7b4288e 100644 --- a/core/src/main/java/org/elasticsearch/search/sort/SortOrder.java +++ b/core/src/main/java/org/elasticsearch/search/sort/SortOrder.java @@ -52,16 +52,12 @@ public enum SortOrder implements Writeable { }; static SortOrder readFromStream(StreamInput in) throws IOException { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= values().length) { - throw new IOException("Unknown SortOrder ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(SortOrder.class); } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(this.ordinal()); + out.writeEnum(this); } public static SortOrder fromString(String op) { diff --git a/core/src/main/java/org/elasticsearch/search/suggest/SortBy.java b/core/src/main/java/org/elasticsearch/search/suggest/SortBy.java index 3cd19c5c2fb..328fc4e8218 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/SortBy.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/SortBy.java @@ -38,15 +38,11 @@ public enum SortBy implements Writeable { @Override public void writeTo(final StreamOutput out) throws IOException { - out.writeVInt(ordinal()); + out.writeEnum(this); } public static SortBy readFromStream(final StreamInput in) throws IOException { - int ordinal = in.readVInt(); - if (ordinal < 0 || ordinal >= values().length) { - throw new IOException("Unknown SortBy ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(SortBy.class); } public static SortBy resolve(final String str) { diff --git a/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestionBuilder.java b/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestionBuilder.java index 72fd41dc5b4..f701ff36426 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestionBuilder.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/term/TermSuggestionBuilder.java @@ -511,15 +511,11 @@ public class TermSuggestionBuilder extends SuggestionBuilder= values().length) { - throw new IOException("Unknown SuggestMode ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(SuggestMode.class); } public static SuggestMode resolve(final String str) { @@ -571,15 +567,11 @@ public class TermSuggestionBuilder extends SuggestionBuilder= values().length) { - throw new IOException("Unknown StringDistanceImpl ordinal [" + ordinal + "]"); - } - return values()[ordinal]; + return in.readEnum(StringDistanceImpl.class); } public static StringDistanceImpl resolve(final String str) { diff --git a/core/src/test/java/org/elasticsearch/common/io/stream/BytesStreamsTests.java b/core/src/test/java/org/elasticsearch/common/io/stream/BytesStreamsTests.java index a8b065343c9..b67000e2b23 100644 --- a/core/src/test/java/org/elasticsearch/common/io/stream/BytesStreamsTests.java +++ b/core/src/test/java/org/elasticsearch/common/io/stream/BytesStreamsTests.java @@ -812,4 +812,34 @@ public class BytesStreamsTests extends ESTestCase { StreamInput in = new BytesArray(Base64.getDecoder().decode("////////////AQAAAAAAAA==")).streamInput(); assertEquals(-1, in.readVLong()); } + + public enum TestEnum { + ONE, + TWO, + THREE + } + + public void testEnum() throws IOException { + TestEnum value = randomFrom(TestEnum.values()); + BytesStreamOutput output = new BytesStreamOutput(); + output.writeEnum(value); + StreamInput input = output.bytes().streamInput(); + assertEquals(value, input.readEnum(TestEnum.class)); + assertEquals(0, input.available()); + } + + public void testInvalidEnum() throws IOException { + BytesStreamOutput output = new BytesStreamOutput(); + int randomNumber = randomInt(); + boolean validEnum = randomNumber >= 0 && randomNumber < TestEnum.values().length; + output.writeVInt(randomNumber); + StreamInput input = output.bytes().streamInput(); + if (validEnum) { + assertEquals(TestEnum.values()[randomNumber], input.readEnum(TestEnum.class)); + } else { + IOException ex = expectThrows(IOException.class, () -> input.readEnum(TestEnum.class)); + assertEquals("Unknown TestEnum ordinal [" + randomNumber + "]", ex.getMessage()); + } + assertEquals(0, input.available()); + } }