1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-10-14 05:27:39 +00:00

Support arguments being coerced from strings

In this case, we use Lua's tostring(x) semantics (well, modulo
metamethods), instead of Java's Object.toString(x) call. This ensures
that values are formatted (mostly) consistently between Lua and Java
methods.

 - Add IArguments.getStringCoerced, which uses Lua's tostring semantics.

 - Add a Coerced<T> wrapper type, which says to use the .getXCoerced
   methods. I'm not thrilled about this interface - there's definitely
   an argument for using annotations - but this is probably more
   consistent for now.

 - Convert existing methods to use this call.

Closes #1445
This commit is contained in:
Jonathan Coates
2023-05-20 18:52:21 +01:00
parent e0216f8792
commit 3112f455ae
18 changed files with 118 additions and 46 deletions

View File

@@ -0,0 +1,26 @@
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.api.lua;
/**
* A wrapper type for "coerced" values.
* <p>
* This is designed to be used with {@link LuaFunction} annotated functions, to mark an argument as being coerced to
* the given type, rather than requiring an exact type.
*
* <h2>Example:</h2>
* <pre>{@code
* @LuaFunction
* public final void doSomething(Coerced<String> myString) {
* var value = myString.value();
* }
* }</pre>
*
* @param value The argument value.
* @param <T> The type of the underlying value.
* @see IArguments#getStringCoerced(int)
*/
public record Coerced<T>(T value) {
}

View File

@@ -154,6 +154,36 @@ public interface IArguments {
return string;
}
/**
* Get the argument, converting it to a string by following Lua conventions.
* <p>
* Unlike {@code Objects.toString(arguments.get(i))}, this may follow Lua's string formatting, so {@code nil} will be
* converted to {@code "nil"} and tables/functions will use their original hash.
*
* @param index The argument number.
* @return The argument's representation as a string.
* @throws LuaException If the argument cannot be converted to Java. This should be thrown in extraneous
* circumstances (if the conversion would allocate too much memory) and should
* <em>not</em> be thrown if the original argument is not present or is an unsupported
* data type (such as a function or userdata).
* @throws IllegalStateException If accessing these arguments outside the scope of the original function. See
* {@link #escapes()}.
* @see Coerced
*/
default String getStringCoerced(int index) throws LuaException {
var value = get(index);
if (value == null) return "nil";
if (value instanceof Boolean || value instanceof String) return value.toString();
if (value instanceof Number number) {
var asDouble = number.doubleValue();
var asInt = (int) asDouble;
return asInt == asDouble ? Integer.toString(asInt) : Double.toString(asDouble);
}
// This is somewhat bogus - the hash codes don't match up - but it's a good approximation.
return String.format("%s: %08x", getType(index), value.hashCode());
}
/**
* Get a string argument as a byte array.
*