|
51 | 51 | import com.oracle.graal.python.builtins.PythonBuiltinClassType;
|
52 | 52 | import com.oracle.graal.python.builtins.PythonBuiltins;
|
53 | 53 | import com.oracle.graal.python.builtins.objects.PNone;
|
| 54 | +import com.oracle.graal.python.builtins.objects.bytes.PBytesLike; |
54 | 55 | import com.oracle.graal.python.builtins.objects.module.PythonModule;
|
55 | 56 | import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
|
56 | 57 | import com.oracle.graal.python.builtins.objects.str.PString;
|
|
63 | 64 | import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
|
64 | 65 | import com.oracle.graal.python.runtime.PythonCore;
|
65 | 66 | import com.oracle.graal.python.runtime.exception.PythonErrorType;
|
| 67 | +import com.oracle.graal.python.runtime.interop.InteropByteArray; |
66 | 68 | import com.oracle.truffle.api.CompilerDirectives;
|
67 | 69 | import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
68 | 70 | import com.oracle.truffle.api.TruffleLanguage.Env;
|
|
72 | 74 | import com.oracle.truffle.api.dsl.NodeFactory;
|
73 | 75 | import com.oracle.truffle.api.dsl.Specialization;
|
74 | 76 | import com.oracle.truffle.api.frame.VirtualFrame;
|
| 77 | +import com.oracle.truffle.api.interop.InteropLibrary; |
| 78 | +import com.oracle.truffle.api.interop.InvalidArrayIndexException; |
75 | 79 | import com.oracle.truffle.api.interop.TruffleObject;
|
| 80 | +import com.oracle.truffle.api.interop.UnsupportedMessageException; |
76 | 81 | import com.oracle.truffle.api.library.CachedLibrary;
|
| 82 | +import com.oracle.truffle.api.library.ExportLibrary; |
| 83 | +import com.oracle.truffle.api.library.ExportMessage; |
77 | 84 |
|
78 | 85 | @CoreFunctions(defineModule = JavaModuleBuiltins.JAVA)
|
79 | 86 | public class JavaModuleBuiltins extends PythonBuiltins {
|
@@ -259,4 +266,92 @@ Object none(VirtualFrame frame, PythonModule mod, Object name,
|
259 | 266 | return lib.callObject(getAttr(frame, mod, lib), frame, name);
|
260 | 267 | }
|
261 | 268 | }
|
| 269 | + |
| 270 | + @Builtin(name = "as_java_byte_array", minNumOfPositionalArgs = 1) |
| 271 | + @GenerateNodeFactory |
| 272 | + abstract static class AsJavaByteArrayNode extends PythonUnaryBuiltinNode { |
| 273 | + @Specialization |
| 274 | + static Object doBytesByteStorage(PBytesLike object) { |
| 275 | + return new PUnsignedBytesWrapper(object); |
| 276 | + } |
| 277 | + |
| 278 | + @Specialization(guards = "lib.isBuffer(object)", limit = "3") |
| 279 | + static Object doBuffer(Object object, |
| 280 | + @CachedLibrary("object") PythonObjectLibrary lib) { |
| 281 | + try { |
| 282 | + return new InteropByteArray(lib.getBufferBytes(object)); |
| 283 | + } catch (UnsupportedMessageException e) { |
| 284 | + throw CompilerDirectives.shouldNotReachHere(); |
| 285 | + } |
| 286 | + } |
| 287 | + |
| 288 | + @Fallback |
| 289 | + Object doError(Object object) { |
| 290 | + throw raise(PythonBuiltinClassType.TypeError, ErrorMessages.BYTESLIKE_OBJ_REQUIRED, object); |
| 291 | + } |
| 292 | + } |
| 293 | + |
| 294 | + /** |
| 295 | + * A simple wrapper object that bit-casts an integer in range {@code 0-255} to a Java |
| 296 | + * {@code byte}. This can be used to expose a bytes-like object to Java as {@code byte[]}. |
| 297 | + */ |
| 298 | + @ExportLibrary(value = InteropLibrary.class, delegateTo = "delegate") |
| 299 | + @SuppressWarnings("static-method") |
| 300 | + static final class PUnsignedBytesWrapper implements TruffleObject { |
| 301 | + final PBytesLike delegate; |
| 302 | + |
| 303 | + PUnsignedBytesWrapper(PBytesLike delegate) { |
| 304 | + this.delegate = delegate; |
| 305 | + } |
| 306 | + |
| 307 | + @ExportMessage |
| 308 | + boolean hasArrayElements( |
| 309 | + @CachedLibrary("this.delegate") InteropLibrary delegateLib) { |
| 310 | + return delegateLib.hasArrayElements(delegate); |
| 311 | + } |
| 312 | + |
| 313 | + @ExportMessage |
| 314 | + boolean isArrayElementReadable(long index, |
| 315 | + @CachedLibrary("this.delegate") InteropLibrary delegateLib) { |
| 316 | + return delegateLib.isArrayElementReadable(delegate, index); |
| 317 | + } |
| 318 | + |
| 319 | + @ExportMessage |
| 320 | + long getArraySize( |
| 321 | + @CachedLibrary("this.delegate") InteropLibrary delegateLib) throws UnsupportedMessageException { |
| 322 | + return delegateLib.getArraySize(delegate); |
| 323 | + } |
| 324 | + |
| 325 | + @ExportMessage |
| 326 | + Object readArrayElement(long index, |
| 327 | + @CachedLibrary("this.delegate") InteropLibrary delegateLib, |
| 328 | + @CachedLibrary(limit = "1") InteropLibrary elementLib) throws InvalidArrayIndexException, UnsupportedMessageException { |
| 329 | + Object element = delegateLib.readArrayElement(delegate, index); |
| 330 | + if (elementLib.fitsInLong(element)) { |
| 331 | + long i = elementLib.asLong(element); |
| 332 | + if (compareUnsigned(i, Byte.MAX_VALUE) <= 0) { |
| 333 | + return (byte) i; |
| 334 | + } else if (compareUnsigned(i, 0xFF) <= 0) { |
| 335 | + return (byte) -(-i & 0xFF); |
| 336 | + } |
| 337 | + } |
| 338 | + throw CompilerDirectives.shouldNotReachHere("bytes object contains non-byte values"); |
| 339 | + } |
| 340 | + |
| 341 | + /** |
| 342 | + * This is taken from {@link Long#compare(long, long)}} (just to avoid a |
| 343 | + * {@code TruffleBoundary}). |
| 344 | + */ |
| 345 | + private static int compare(long x, long y) { |
| 346 | + return (x < y) ? -1 : ((x == y) ? 0 : 1); |
| 347 | + } |
| 348 | + |
| 349 | + /** |
| 350 | + * This is taken from {@link Long#compareUnsigned(long, long)}} (just to avoid a |
| 351 | + * {@code TruffleBoundary}). |
| 352 | + */ |
| 353 | + private static int compareUnsigned(long x, long y) { |
| 354 | + return compare(x + Long.MIN_VALUE, y + Long.MIN_VALUE); |
| 355 | + } |
| 356 | + } |
262 | 357 | }
|
0 commit comments