Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add nio Buffers to Painless #79870

Merged
merged 2 commits into from
Oct 26, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ public final class PainlessPlugin extends Plugin implements ScriptPlugin, Extens
"java.util.txt",
"java.util.function.txt",
"java.util.regex.txt",
"java.util.stream.txt"
"java.util.stream.txt",
"java.nio.txt"
};
public static final List<Whitelist> BASE_WHITELISTS =
Collections.singletonList(WhitelistLoader.loadFromResourceFiles(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0 and the Server Side Public License, v 1; you may not use this file except
# in compliance with, at your election, the Elastic License 2.0 or the Server
# Side Public License, v 1.
#

class java.nio.Buffer {
int limit()
}

class java.nio.ByteBuffer {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also expose the wrap methods? Otherwise null would be the only value available to pass to getValue on a binary field?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add this.

CharBuffer asCharBuffer()
DoubleBuffer asDoubleBuffer()
FloatBuffer asFloatBuffer()
IntBuffer asIntBuffer()
LongBuffer asLongBuffer()
ShortBuffer asShortBuffer()
byte get(int)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we also need order, otherwise the order is always big endian. I think is ok to have a such a setter because it modifies the byte buffer object, which is transient, not the underlying data.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add this too.

# TODO: https:#github.com/elastic/elasticsearch/issues/79867
# ByteBuffer get(int, byte[])
# ByteBuffer get(int, byte[], int, int)
char getChar(int)
double getDouble(int)
float getFloat(int)
int getInt(int)
long getLong(int)
short getShort(int)
}

class java.nio.CharBuffer {
char get(int)
# TODO: https:#github.com/elastic/elasticsearch/issues/79867
# CharBuffer get(int, char[])
# CharBuffer get(int, char[], int, int)
}

class java.nio.DoubleBuffer {
double get(int)
# TODO: https:#github.com/elastic/elasticsearch/issues/79867
# DoubleBuffer get(int, double[])
# DoubleBuffer get(int, double[], int, int)
}

class java.nio.FloatBuffer {
float get(int)
# TODO: https:#github.com/elastic/elasticsearch/issues/79867
# FloatBuffer get(int, float[])
# FloatBuffer get(int, float[], int, int)
}

class java.nio.IntBuffer {
int get(int)
# TODO: https:#github.com/elastic/elasticsearch/issues/79867
# IntBuffer get(int, int[])
# IntBuffer get(int, int[], int, int)
}

class java.nio.LongBuffer {
long get(int)
# TODO: https:#github.com/elastic/elasticsearch/issues/79867
# LongBuffer get(int, long[])
# LongBuffer get(int, long[], int, int)
}

class java.nio.ShortBuffer {
short get(int)
# TODO: https:#github.com/elastic/elasticsearch/issues/79867
# ShortBuffer get(int, short[])
# ShortBuffer get(int, short[], int, int)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.painless;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
import java.util.Collections;
import java.util.Map;

public class BufferTests extends ScriptTestCase {

public void testByteBufferMethods() {
ByteBuffer bb = ByteBuffer.wrap(new byte[] {0, 1, 2, 3, 4, 5, 6, 7});
Map<String, Object> params = Collections.singletonMap("bb", bb);

assertEquals(bb.limit(), exec("def bb = params['bb']; bb.limit()", params, true));
assertEquals(bb.limit(), exec("ByteBuffer bb = params['bb']; bb.limit()", params, true));

assertEquals(bb.get(0), exec("def bb = params['bb']; bb.get(0)", params, true));
assertEquals(bb.get(0), exec("ByteBuffer bb = params['bb']; bb.get(0)", params, true));
assertEquals(bb.get(1), exec("def bb = params['bb']; bb.get(1)", params, true));
assertEquals(bb.get(1), exec("ByteBuffer bb = params['bb']; bb.get(1)", params, true));

assertEquals(bb.getChar(0), exec("def bb = params['bb']; bb.getChar(0)", params, true));
assertEquals(bb.getChar(0), exec("ByteBuffer bb = params['bb']; bb.getChar(0)", params, true));

assertEquals(bb.getDouble(0), (double)exec("def bb = params['bb']; bb.getDouble(0)", params, true), 0.1);
assertEquals(bb.getDouble(0), (double)exec("ByteBuffer bb = params['bb']; bb.getDouble(0)", params, true), 0.1);

assertEquals(bb.getFloat(0), (float)exec("def bb = params['bb']; bb.getFloat(0)", params, true), 0.1);
assertEquals(bb.getFloat(0), (float)exec("ByteBuffer bb = params['bb']; bb.getFloat(0)", params, true), 0.1);

assertEquals(bb.getInt(0), exec("def bb = params['bb']; bb.getInt(0)", params, true));
assertEquals(bb.getInt(0), exec("ByteBuffer bb = params['bb']; bb.getInt(0)", params, true));

assertEquals(bb.getLong(0), exec("def bb = params['bb']; bb.getLong(0)", params, true));
assertEquals(bb.getLong(0), exec("ByteBuffer bb = params['bb']; bb.getLong(0)", params, true));

assertEquals(bb.getShort(0), exec("def bb = params['bb']; bb.getShort(0)", params, true));
assertEquals(bb.getShort(0), exec("ByteBuffer bb = params['bb']; bb.getShort(0)", params, true));

assertEquals(bb.asCharBuffer(), exec("def bb = params['bb']; bb.asCharBuffer()", params, true));
assertEquals(bb.asCharBuffer(), exec("ByteBuffer bb = params['bb']; bb.asCharBuffer()", params, true));

assertEquals(bb.asDoubleBuffer(), exec("def bb = params['bb']; bb.asDoubleBuffer()", params, true));
assertEquals(bb.asDoubleBuffer(), exec("ByteBuffer bb = params['bb']; bb.asDoubleBuffer()", params, true));

assertEquals(bb.asFloatBuffer(), exec("def bb = params['bb']; bb.asFloatBuffer()", params, true));
assertEquals(bb.asFloatBuffer(), exec("ByteBuffer bb = params['bb']; bb.asFloatBuffer()", params, true));

assertEquals(bb.asIntBuffer(), exec("def bb = params['bb']; bb.asIntBuffer()", params, true));
assertEquals(bb.asIntBuffer(), exec("ByteBuffer bb = params['bb']; bb.asIntBuffer()", params, true));

assertEquals(bb.asLongBuffer(), exec("def bb = params['bb']; bb.asLongBuffer()", params, true));
assertEquals(bb.asLongBuffer(), exec("ByteBuffer bb = params['bb']; bb.asLongBuffer()", params, true));

assertEquals(bb.asShortBuffer(), exec("def bb = params['bb']; bb.asShortBuffer()", params, true));
assertEquals(bb.asShortBuffer(), exec("ByteBuffer bb = params['bb']; bb.asShortBuffer()", params, true));
}

public void testCharBufferMethods() {
CharBuffer bb = CharBuffer.wrap(new char[] {0, 1, 2, 3, 4, 5, 6, 7});
Map<String, Object> params = Collections.singletonMap("bb", bb);

assertEquals(bb.limit(), exec("def bb = params['bb']; bb.limit()", params, true));
assertEquals(bb.limit(), exec("CharBuffer bb = params['bb']; bb.limit()", params, true));

assertEquals(bb.get(0), exec("def bb = params['bb']; bb.get(0)", params, true));
assertEquals(bb.get(0), exec("CharBuffer bb = params['bb']; bb.get(0)", params, true));
assertEquals(bb.get(1), exec("def bb = params['bb']; bb.get(1)", params, true));
assertEquals(bb.get(1), exec("CharBuffer bb = params['bb']; bb.get(1)", params, true));
}

public void testDoubleBufferMethods() {
DoubleBuffer bb = DoubleBuffer.wrap(new double[] {0, 1, 2, 3, 4, 5, 6, 7});
Map<String, Object> params = Collections.singletonMap("bb", bb);

assertEquals(bb.limit(), exec("def bb = params['bb']; bb.limit()", params, true));
assertEquals(bb.limit(), exec("DoubleBuffer bb = params['bb']; bb.limit()", params, true));

assertEquals(bb.get(0), exec("def bb = params['bb']; bb.get(0)", params, true));
assertEquals(bb.get(0), exec("DoubleBuffer bb = params['bb']; bb.get(0)", params, true));
assertEquals(bb.get(1), exec("def bb = params['bb']; bb.get(1)", params, true));
assertEquals(bb.get(1), exec("DoubleBuffer bb = params['bb']; bb.get(1)", params, true));
}

public void testFloatBufferMethods() {
FloatBuffer bb = FloatBuffer.wrap(new float[] {0, 1, 2, 3, 4, 5, 6, 7});
Map<String, Object> params = Collections.singletonMap("bb", bb);

assertEquals(bb.limit(), exec("def bb = params['bb']; bb.limit()", params, true));
assertEquals(bb.limit(), exec("FloatBuffer bb = params['bb']; bb.limit()", params, true));

assertEquals(bb.get(0), exec("def bb = params['bb']; bb.get(0)", params, true));
assertEquals(bb.get(0), exec("FloatBuffer bb = params['bb']; bb.get(0)", params, true));
assertEquals(bb.get(1), exec("def bb = params['bb']; bb.get(1)", params, true));
assertEquals(bb.get(1), exec("FloatBuffer bb = params['bb']; bb.get(1)", params, true));
}

public void testIntBufferMethods() {
IntBuffer bb = IntBuffer.wrap(new int[] {0, 1, 2, 3, 4, 5, 6, 7});
Map<String, Object> params = Collections.singletonMap("bb", bb);

assertEquals(bb.limit(), exec("def bb = params['bb']; bb.limit()", params, true));
assertEquals(bb.limit(), exec("IntBuffer bb = params['bb']; bb.limit()", params, true));

assertEquals(bb.get(0), exec("def bb = params['bb']; bb.get(0)", params, true));
assertEquals(bb.get(0), exec("IntBuffer bb = params['bb']; bb.get(0)", params, true));
assertEquals(bb.get(1), exec("def bb = params['bb']; bb.get(1)", params, true));
assertEquals(bb.get(1), exec("IntBuffer bb = params['bb']; bb.get(1)", params, true));
}

public void testLongBufferMethods() {
LongBuffer bb = LongBuffer.wrap(new long[] {0, 1, 2, 3, 4, 5, 6, 7});
Map<String, Object> params = Collections.singletonMap("bb", bb);

assertEquals(bb.limit(), exec("def bb = params['bb']; bb.limit()", params, true));
assertEquals(bb.limit(), exec("LongBuffer bb = params['bb']; bb.limit()", params, true));

assertEquals(bb.get(0), exec("def bb = params['bb']; bb.get(0)", params, true));
assertEquals(bb.get(0), exec("LongBuffer bb = params['bb']; bb.get(0)", params, true));
assertEquals(bb.get(1), exec("def bb = params['bb']; bb.get(1)", params, true));
assertEquals(bb.get(1), exec("LongBuffer bb = params['bb']; bb.get(1)", params, true));
}

public void testShortBufferMethods() {
ShortBuffer bb = ShortBuffer.wrap(new short[] {0, 1, 2, 3, 4, 5, 6, 7});
Map<String, Object> params = Collections.singletonMap("bb", bb);

assertEquals(bb.limit(), exec("def bb = params['bb']; bb.limit()", params, true));
assertEquals(bb.limit(), exec("ShortBuffer bb = params['bb']; bb.limit()", params, true));

assertEquals(bb.get(0), exec("def bb = params['bb']; bb.get(0)", params, true));
assertEquals(bb.get(0), exec("ShortBuffer bb = params['bb']; bb.get(0)", params, true));
assertEquals(bb.get(1), exec("def bb = params['bb']; bb.get(1)", params, true));
assertEquals(bb.get(1), exec("ShortBuffer bb = params['bb']; bb.get(1)", params, true));
}
}