java-commons/muscript/src/main/java/io/gitlab/jfronny/muscript/data/dynamic/Dynamic.java

110 lines
3.5 KiB
Java

package io.gitlab.jfronny.muscript.data.dynamic;
import io.gitlab.jfronny.commons.StringFormatter;
import io.gitlab.jfronny.muscript.StandardLib;
import io.gitlab.jfronny.muscript.ast.DynamicExpr;
import io.gitlab.jfronny.muscript.ast.Expr;
import io.gitlab.jfronny.muscript.compiler.ExprWriter;
import io.gitlab.jfronny.muscript.compiler.Parser;
import io.gitlab.jfronny.muscript.data.dynamic.additional.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
/**
* Represents a value of an unknown type
* Override toString(StringBuilder) to support custom serialization (note: the serialized form is ran with muScript to generate the tree)
* @param <T> the type represented
*/
public sealed interface Dynamic<T> permits DBool, DCallable, DList, DNull, DNumber, DObject, DString, DynamicBase {
/**
* Deserialize simply dynamic values. DOES NOT SUPPORT CALLABLES!
* Use Parser.parse() if you truly need to deserialize them, but be aware that that might enable DOS attacks
*/
static Dynamic<?> deserialize(String source) {
DynamicExpr expr = Parser.parse(source).asDynamicExpr();
if (!DirectPreconditionVisitor.visit(expr)) throw new IllegalArgumentException("This expression does not directly express a dynamic and may not be loaded this way");
return expr.get(StandardLib.createScope());
}
static String serialize(Dynamic<?> dynamic) {
StringBuilder sb = new StringBuilder();
try (ExprWriter ew = new ExprWriter(sb, true)) {
dynamic.serialize(ew);
} catch (IOException e) {
throw new RuntimeException("Could not stringify", e);
}
return sb.toString();
}
static boolean isNull(Dynamic<?> dynamic) {
return dynamic == null || dynamic instanceof DNull;
}
static @NotNull Dynamic<?> fromNullable(@Nullable Dynamic<?> dynamic) {
return dynamic == null ? new DNull() : dynamic;
}
default void serialize(ExprWriter writer) throws IOException {
toExpr().decompile(writer);
}
Expr<?> toExpr();
T getValue();
default boolean isBool() {
return this instanceof DBool;
}
default DBool asBool() {
if (this instanceof DBool bool) return bool;
else throw new DynamicTypeConversionException("bool", this);
}
default boolean isNumber() {
return this instanceof DNumber;
}
default DNumber asNumber() {
if (this instanceof DNumber number) return number;
else throw new DynamicTypeConversionException("number", this);
}
default boolean isString() {
return this instanceof DString;
}
default DString asString() {
if (this instanceof DString string) return string;
else return DFinal.of(StringFormatter.toString(getValue()));
}
default boolean isObject() {
return this instanceof DObject;
}
default DObject asObject() {
if (this instanceof DObject object) return object;
else throw new DynamicTypeConversionException("object", this);
}
default boolean isList() {
return this instanceof DList;
}
default DList asList() {
if (this instanceof DList list) return list;
else throw new DynamicTypeConversionException("list", this);
}
default boolean isCallable() {
return this instanceof DCallable;
}
default DCallable asCallable() {
if (this instanceof DCallable callable) return callable;
else throw new DynamicTypeConversionException("callable", this);
}
}