From 228965054a3ba235033dd958ff7c7306c83f46b7 Mon Sep 17 00:00:00 2001 From: squid233 <60126026+squid233@users.noreply.github.com> Date: Sun, 3 Dec 2023 14:59:50 +0800 Subject: [PATCH] Added annotation Default; update javadoc --- build.gradle.kts | 85 ++++++++++--------- .../overrun/marshal/test/CMarshalTest.java | 6 +- gradle.properties | 18 ++-- src/main/java/module-info.java | 19 ++++- src/main/java/overrun/marshal/BoolHelper.java | 19 +++++ src/main/java/overrun/marshal/Checks.java | 20 ++++- src/main/java/overrun/marshal/Custom.java | 11 +++ src/main/java/overrun/marshal/Default.java | 46 ++++++++++ src/main/java/overrun/marshal/FixedSize.java | 12 +++ .../java/overrun/marshal/LibrarySelector.java | 3 + .../java/overrun/marshal/MarshalScope.java | 15 ++++ src/main/java/overrun/marshal/Native.java | 27 +++++- src/main/java/overrun/marshal/NativeApi.java | 47 ++++++++++ .../overrun/marshal/NativeApiProcessor.java | 69 ++++++++++++--- src/main/java/overrun/marshal/Overload.java | 16 ++++ src/main/java/overrun/marshal/Ref.java | 9 ++ .../java/overrun/marshal/package-info.java | 24 ++++++ 17 files changed, 376 insertions(+), 70 deletions(-) create mode 100644 src/main/java/overrun/marshal/Default.java create mode 100644 src/main/java/overrun/marshal/package-info.java diff --git a/build.gradle.kts b/build.gradle.kts index 64703ed..127aaae 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -106,30 +106,6 @@ allprojects { if (JavaVersion.current() < javaVersion) { toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) } - if (hasJavadocJar.toBoolean()) withJavadocJar() - if (hasSourcesJar.toBoolean()) withSourcesJar() - } - - tasks.withType { - isFailOnError = false - options { - encoding = "UTF-8" - locale = "en_US" - windowTitle = "$projName $projVersion Javadoc" - if (this is StandardJavadocDocletOptions) { - charSet = "UTF-8" - isAuthor = true - if (jdkEarlyAccessDoc == null) { - links("https://docs.oracle.com/en/java/javase/$jdkVersion/docs/api/") - } else { - links("https://download.java.net/java/early_access/$jdkEarlyAccessDoc/docs/api/") - } - if (jdkEnablePreview.toBoolean()) { - addBooleanOption("-enable-preview", true) - addStringOption("source", jdkVersion) - } - } - } } //application { @@ -151,23 +127,6 @@ allprojects { ) } - if (hasSourcesJar.toBoolean()) { - tasks.named("sourcesJar") { - dependsOn(tasks["classes"]) - archiveClassifier = "sources" - from(sourceSets["main"].allSource) - } - } - - if (hasJavadocJar.toBoolean()) { - tasks.named("javadocJar") { - val javadoc by tasks - dependsOn(javadoc) - archiveClassifier = "javadoc" - from(javadoc) - } - } - tasks.withType { archiveBaseName = projArtifactId from(rootProject.file(projLicenseFileName)).rename( @@ -181,6 +140,50 @@ tasks.withType { options.compilerArgs.add("-proc:none") } +java { + if (hasJavadocJar.toBoolean()) withJavadocJar() + if (hasSourcesJar.toBoolean()) withSourcesJar() +} + +tasks.withType { + isFailOnError = false + options { + encoding = "UTF-8" + locale = "en_US" + windowTitle = "$projName $projVersion Javadoc" + if (this is StandardJavadocDocletOptions) { + charSet = "UTF-8" + isAuthor = true + if (jdkEarlyAccessDoc == null) { + links("https://docs.oracle.com/en/java/javase/$jdkVersion/docs/api/") + } else { + links("https://download.java.net/java/early_access/$jdkEarlyAccessDoc/docs/api/") + } + if (jdkEnablePreview.toBoolean()) { + addBooleanOption("-enable-preview", true) + addStringOption("source", jdkVersion) + } + } + } +} + +if (hasSourcesJar.toBoolean()) { + tasks.named("sourcesJar") { + dependsOn(tasks["classes"]) + archiveClassifier = "sources" + from(sourceSets["main"].allSource) + } +} + +if (hasJavadocJar.toBoolean()) { + tasks.named("javadocJar") { + val javadoc by tasks + dependsOn(javadoc) + archiveClassifier = "javadoc" + from(javadoc) + } +} + if (hasPublication.toBoolean() && publicationRepo != null) { publishing.publications { register("mavenJava") { diff --git a/demo/src/main/java/overrun/marshal/test/CMarshalTest.java b/demo/src/main/java/overrun/marshal/test/CMarshalTest.java index 7c5741d..e4d8f9d 100644 --- a/demo/src/main/java/overrun/marshal/test/CMarshalTest.java +++ b/demo/src/main/java/overrun/marshal/test/CMarshalTest.java @@ -44,7 +44,7 @@ public interface CMarshalTest { int testWithReturnValue(); - @Native(optional = true) + @Default void testWithOptional(); void testWithArgument(int i, MemorySegment holder); @@ -85,8 +85,8 @@ public interface CMarshalTest { @param segment A memory segment @return Another memory segment""", entrypoint = "testAllFeatures", - scope = MarshalScope.PROTECTED, - optional = true + scope = MarshalScope.PROTECTED ) + @Default("MemorySegment.NULL") MemorySegment testAll(MemorySegment segment); } diff --git a/gradle.properties b/gradle.properties index 7ca950a..c27b9a2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,24 +1,24 @@ # Gradle Options org.gradle.jvmargs=-Dfile.encoding=UTF-8 -hasPublication=false -publicationSigning=false +hasPublication=true +publicationSigning=true -hasJavadocJar=false -hasSourcesJar=false +hasJavadocJar=true +hasSourcesJar=true # Project Information projGroupId=io.github.over-run projArtifactId=marshal # The project name should only contain lowercase letters, numbers and hyphen. projName=marshal -projVersion=0.1.0-SNAPSHOT +projVersion=0.1.0-alpha.0 projDesc=Marshaller of native libraries # Uncomment them if you want to publish to maven repository. -#projUrl=https://github.com/Over-Run/project-template -#projLicenseUrl=https://raw.githubusercontent.com/Over-Run/project-template/main/LICENSE -#projScmConnection=scm:git:https://github.com/Over-Run/project-template.git -#projScmUrl=https://github.com/Over-Run/project-template.git +projUrl=https://github.com/Over-Run/marshal +projLicenseUrl=https://raw.githubusercontent.com/Over-Run/marshal/main/LICENSE +projScmConnection=scm:git:https://github.com/Over-Run/marshal.git +projScmUrl=https://github.com/Over-Run/marshal.git projLicense=MIT projLicenseFileName=LICENSE diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index f97596c..da2528d 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -1,4 +1,22 @@ +/* + * MIT License + * + * Copyright (c) 2023 Overrun Organization + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + */ + /** + * The core module + * * @author squid233 * @since 0.1.0 */ @@ -6,5 +24,4 @@ exports overrun.marshal; requires java.compiler; - requires jdk.compiler; } diff --git a/src/main/java/overrun/marshal/BoolHelper.java b/src/main/java/overrun/marshal/BoolHelper.java index 5c1d8bb..31efa75 100644 --- a/src/main/java/overrun/marshal/BoolHelper.java +++ b/src/main/java/overrun/marshal/BoolHelper.java @@ -31,6 +31,13 @@ private BoolHelper() { //no instance } + /** + * Allocates a memory segment with the given boolean array. + * + * @param allocator the segment allocator + * @param arr the boolean array + * @return the memory segment + */ public static MemorySegment of(SegmentAllocator allocator, boolean[] arr) { final MemorySegment segment = allocator.allocate(ValueLayout.JAVA_BOOLEAN, arr.length); for (int i = 0; i < arr.length; i++) { @@ -39,6 +46,12 @@ public static MemorySegment of(SegmentAllocator allocator, boolean[] arr) { return segment; } + /** + * Copies data from the given source memory segment into a boolean array. + * + * @param src the source + * @param dst the destination + */ public static void copy(MemorySegment src, boolean[] dst) { final int length = checkArraySize(Math.min(src.byteSize(), dst.length)); for (int i = 0; i < length; i++) { @@ -46,6 +59,12 @@ public static void copy(MemorySegment src, boolean[] dst) { } } + /** + * Converts a memory segment into a boolean array. + * + * @param segment the memory segment + * @return the boolean array + */ public static boolean[] toArray(MemorySegment segment) { boolean[] b = new boolean[checkArraySize(segment.byteSize())]; for (int i = 0; i < b.length; i++) { diff --git a/src/main/java/overrun/marshal/Checks.java b/src/main/java/overrun/marshal/Checks.java index 6288dbe..42ed2e6 100644 --- a/src/main/java/overrun/marshal/Checks.java +++ b/src/main/java/overrun/marshal/Checks.java @@ -19,16 +19,29 @@ import java.util.function.Supplier; /** + * Checks + * * @author squid233 * @since 0.1.0 */ public final class Checks { + /** + * Check size of a fixed size array argument. Default value: {@code true} + * + * @see FixedSize + */ public static final Entry CHECK_ARRAY_SIZE = new Entry<>(() -> true); private Checks() { //no instance } + /** + * Checks the array size. + * + * @param expected the expected size + * @param got the got size + */ public static void checkArraySize(int expected, int got) { if (CHECK_ARRAY_SIZE.get() && expected != got) { throw new IllegalArgumentException("Expected array of size " + expected + ", got " + got); @@ -36,6 +49,8 @@ public static void checkArraySize(int expected, int got) { } /** + * A check entry + * * @author squid233 * @since 0.1.0 */ @@ -43,10 +58,13 @@ public static final class Entry { private final Supplier supplier; private T value; - public Entry(Supplier supplier) { + private Entry(Supplier supplier) { this.supplier = supplier; } + /** + * {@return the value of this entry} + */ public T get() { if (value == null) { value = supplier.get(); diff --git a/src/main/java/overrun/marshal/Custom.java b/src/main/java/overrun/marshal/Custom.java index 45966c3..f87ee19 100644 --- a/src/main/java/overrun/marshal/Custom.java +++ b/src/main/java/overrun/marshal/Custom.java @@ -19,6 +19,14 @@ import java.lang.annotation.*; /** + * Marks a method that uses custom code instead of generated code. + *

Example

+ *
{@code
+ * @Custom("""
+ *     System.out.println("Hello world");""")
+ * void myCode();
+ * }
+ * * @author squid233 * @since 0.1.0 */ @@ -26,5 +34,8 @@ @Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Custom { + /** + * {@return the custom code} + */ String value(); } diff --git a/src/main/java/overrun/marshal/Default.java b/src/main/java/overrun/marshal/Default.java new file mode 100644 index 0000000..bdfc5a2 --- /dev/null +++ b/src/main/java/overrun/marshal/Default.java @@ -0,0 +1,46 @@ +/* + * MIT License + * + * Copyright (c) 2023 Overrun Organization + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + */ + +package overrun.marshal; + +import java.lang.annotation.*; + +/** + * Marks a method that has a default return value. + *

+ * A method marked as {@code @Default} will not throw an exception or be invoked + * if it couldn't be found in the specified library. + *

Example

+ *
{@code
+ * @Default
+ * void functionThatMightBeAbsent();
+ *
+ * @Default("42")
+ * int anotherFunction();
+ * }
+ * + * @author squid233 + * @since 0.1.0 + */ +@Documented +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.SOURCE) +public @interface Default { + /** + * {@return the default value of the method} + */ + String value() default ""; +} diff --git a/src/main/java/overrun/marshal/FixedSize.java b/src/main/java/overrun/marshal/FixedSize.java index 2b6ff9c..806efac 100644 --- a/src/main/java/overrun/marshal/FixedSize.java +++ b/src/main/java/overrun/marshal/FixedSize.java @@ -19,12 +19,24 @@ import java.lang.annotation.*; /** + * Marks an array parameter as a fixed size array. + *

+ * The generated code will try to check the size of a passing array. + *

Example

+ *
{@code
+ * void set(@FixedSize(3) int[] vec);
+ * }
+ * * @author squid233 + * @see Checks#CHECK_ARRAY_SIZE * @since 0.1.0 */ @Documented @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.SOURCE) public @interface FixedSize { + /** + * {@return the size of the array} + */ int value(); } diff --git a/src/main/java/overrun/marshal/LibrarySelector.java b/src/main/java/overrun/marshal/LibrarySelector.java index 5848f81..df054ad 100644 --- a/src/main/java/overrun/marshal/LibrarySelector.java +++ b/src/main/java/overrun/marshal/LibrarySelector.java @@ -17,7 +17,10 @@ package overrun.marshal; /** + * A library selector. + * * @author squid233 + * @see NativeApi * @since 0.1.0 */ public interface LibrarySelector { diff --git a/src/main/java/overrun/marshal/MarshalScope.java b/src/main/java/overrun/marshal/MarshalScope.java index d7568e3..f834a4a 100644 --- a/src/main/java/overrun/marshal/MarshalScope.java +++ b/src/main/java/overrun/marshal/MarshalScope.java @@ -17,13 +17,28 @@ package overrun.marshal; /** + * The marshal scope that specifies the access modifier of a method. + * * @author squid233 + * @see Native * @since 0.1.0 */ public enum MarshalScope { + /** + * {@code public} access + */ PUBLIC("public"), + /** + * {@code protected} access + */ PROTECTED("protected"), + /** + * package-private access + */ PACKAGE_PRIVATE(""), + /** + * {@code private} access + */ PRIVATE("private"); private final String toStringValue; diff --git a/src/main/java/overrun/marshal/Native.java b/src/main/java/overrun/marshal/Native.java index fb4e3f3..91112af 100644 --- a/src/main/java/overrun/marshal/Native.java +++ b/src/main/java/overrun/marshal/Native.java @@ -19,6 +19,20 @@ import java.lang.annotation.*; /** + * Applies additional settings to a method. + *

Example

+ *
{@code
+ * @Native(doc = """
+ *     The documentation
+ *
+ *     @param dst the destination
+ *     @return 1 if success; 0 otherwise""",
+ *     entrypoint = "getStatus",
+ *     scope = MarshalScope.PROTECTED
+ * )
+ * int ngetStatus(MemorySegment dst);
+ * }
+ * * @author squid233 * @since 0.1.0 */ @@ -26,11 +40,20 @@ @Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Native { + /** + * {@return the javadoc of the method} + */ String doc() default ""; + /** + * Uses the specified entrypoint (the native name of the function), instead of the method name. + * + * @return the entrypoint name of the method + */ String entrypoint() default ""; + /** + * {@return the access modifier of the method} + */ MarshalScope scope() default MarshalScope.PUBLIC; - - boolean optional() default false; } diff --git a/src/main/java/overrun/marshal/NativeApi.java b/src/main/java/overrun/marshal/NativeApi.java index 751e120..5cabfd3 100644 --- a/src/main/java/overrun/marshal/NativeApi.java +++ b/src/main/java/overrun/marshal/NativeApi.java @@ -19,18 +19,65 @@ import java.lang.annotation.*; /** + * Marks a class or interface as a native API provider. + *

Constants

+ * The generated file will include constants of primitive + * (boolean, byte, short, int, long, float, double) and String types in the marked class or interface. + *

Methods

+ * The generator tries to generate static methods that invoke native functions. + *

+ * The {@link Custom @Custom} annotation overwrite all generated method body with the custom code. + *

+ * Some settings can be applied by marking methods with {@link Native @Native}. + *

Overload Methods

+ * An overload method, marked with {@link Overload @Overload}, automatically invokes another method with the same name. + * See {@linkplain Overload documentation} for more information. + *

+ * Methods without {@link Overload @Overload} marked + * converts parameters of {@link String} and array types into {@link java.lang.foreign.MemorySegment MemorySegment}. + *

Parameter Annotations

+ * See {@link FixedSize @FixedSize} and {@link Ref @Ref}. + *

Example

+ *
{@code
+ * @NativeApi(libname = "libGL.so", name = "GL")
+ * interface CGL {
+ *     int COLOR_BUFFER_BIT = 0x00004000;
+ *     void glClear(int mask);
+ * }
+ * }
+ * * @author squid233 + * @see Custom + * @see Native + * @see Overload + * @see FixedSize + * @see Ref * @since 0.1.0 */ @Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface NativeApi { + /** + * {@return the name of the native library} + *

+ * Might be a filename with an extension + * or the basename of {@linkplain #selector() the library selector}. + */ String libname(); + /** + * {@return the name of the generated class} + */ String name(); + /** + * {@return the {@linkplain LibrarySelector library selector}} + */ Class selector() default LibrarySelector.class; + /** + * {@return {@code true} if the generated class should be {@code final}; {@code false} otherwise} + */ boolean makeFinal() default true; } diff --git a/src/main/java/overrun/marshal/NativeApiProcessor.java b/src/main/java/overrun/marshal/NativeApiProcessor.java index 719d372..e15c98b 100644 --- a/src/main/java/overrun/marshal/NativeApiProcessor.java +++ b/src/main/java/overrun/marshal/NativeApiProcessor.java @@ -39,12 +39,14 @@ import java.util.stream.Collectors; /** + * The annotation processor + * * @author squid233 * @since 0.1.0 */ @SupportedAnnotationTypes("overrun.marshal.NativeApi") @SupportedSourceVersion(SourceVersion.RELEASE_22) -public class NativeApiProcessor extends AbstractProcessor { +public final class NativeApiProcessor extends AbstractProcessor { private void processClasses(RoundEnvironment roundEnv) { final Set marshalApis = roundEnv.getElementsAnnotatedWith(NativeApi.class); final Set types = ElementFilter.typesIn(marshalApis); @@ -89,6 +91,7 @@ private void writeFile( sb.append(""" import overrun.marshal.BoolHelper; import overrun.marshal.Checks; + import overrun.marshal.Default; import overrun.marshal.FixedSize; import overrun.marshal.Ref; @@ -132,7 +135,7 @@ private void appendMethodDecl(TypeElement type, List methods, final TypeMirror returnType = method.getReturnType(); final TypeKind returnTypeKind = returnType.getKind(); final var parameters = method.getParameters(); - // check @Ref and @FixedSize + // check annotations checkParamAnnotation(type, method, parameters); final boolean array = isArray(returnType); @@ -140,10 +143,10 @@ private void appendMethodDecl(TypeElement type, List methods, final Native annotation = method.getAnnotation(Native.class); final Overload overloadAnnotation = method.getAnnotation(Overload.class); final Custom customAnnotation = method.getAnnotation(Custom.class); + final Default defaultAnnotation = method.getAnnotation(Default.class); final boolean shouldInsertAllocator = parameters.stream().anyMatch(e -> { final TypeMirror type1 = e.asType(); - final TypeKind kind = type1.getKind(); - return kind == TypeKind.ARRAY || (kind == TypeKind.DECLARED && isString(type1)); + return isArray(type1) || (type1.getKind() == TypeKind.DECLARED && isString(type1)); // TODO: 2023/12/2 Struct }); final boolean notVoid = returnTypeKind != TypeKind.VOID; @@ -162,6 +165,18 @@ private void appendMethodDecl(TypeElement type, List methods, // javadoc appendJavadoc(sb, annotation); + // annotations + if (defaultAnnotation != null) { + sb.append(" @") + .append(Default.class.getSimpleName()); + if (!defaultAnnotation.value().isBlank()) { + sb.append("(\"") + .append(defaultAnnotation.value()) + .append("\")"); + } + sb.append('\n'); + } + sb.append(" ") // access modifier .append(annotation != null ? annotation.scope() : "public") @@ -260,16 +275,43 @@ private void appendMethodBody(TypeElement type, sb.append(" return $_marshalResult;\n"); } } else { + final Default defaulted = method.getAnnotation(Default.class); + final boolean isDefaulted = defaulted != null; + if (isDefaulted && notVoid && defaulted.value().isBlank()) { + printError(type + "::" + method + ": Default non-void method must have a default return value"); + return; + } + final String entrypoint = methodEntrypoint(method); + sb.append(" try {\n "); + + if (isDefaulted) { + sb.append("if (") + .append(entrypoint) + .append(" != null) {\n "); + } + if (notVoid) { sb.append("return (").append(javaReturnType).append(") "); } - sb.append(methodEntrypoint(method)).append(".invokeExact("); - // parameters - sb.append(parameters.stream() - .map(VariableElement::getSimpleName) - .collect(Collectors.joining(", "))); - sb.append(");\n } catch (Throwable e) { throw new AssertionError(\"should not reach here\", e); }\n"); + sb.append(entrypoint).append(".invokeExact(") + // parameters + .append(parameters.stream() + .map(VariableElement::getSimpleName) + .collect(Collectors.joining(", "))) + .append(");\n"); + + if (isDefaulted) { + sb.append(" }"); + if (notVoid) { + sb.append(" else { return ") + .append(defaulted.value()) + .append("; }"); + } + sb.append('\n'); + } + + sb.append(" } catch (Throwable e) { throw new AssertionError(\"should not reach here\", e); }\n"); } } @@ -281,11 +323,11 @@ private static void appendParameters(StringBuilder sb, boolean shouldInsertAlloc .map(e -> { final Ref ref = e.getAnnotation(Ref.class); final String refString = ref != null ? - "@Ref" + (ref.nullable() ? "(nullable = true) " : " ") : + "@" + Ref.class.getSimpleName() + (ref.nullable() ? "(nullable = true) " : " ") : ""; final FixedSize fixedSize = e.getAnnotation(FixedSize.class); final String fixedSizeString = fixedSize != null ? - "@FixedSize(" + fixedSize.value() + ") " : + "@" + FixedSize.class.getSimpleName() + "(" + fixedSize.value() + ") " : ""; return refString + fixedSizeString + toTargetType(e.asType(), overload) + " " + e.getSimpleName(); }) @@ -348,6 +390,7 @@ private void appendMethodHandles(TypeElement type, StringBuilder sb, List { final ExecutableElement method = entry1.getValue(); final Native annotation = method.getAnnotation(Native.class); + final Default defaulted = method.getAnnotation(Default.class); final StringBuilder sb1 = new StringBuilder(256); sb1.append(" ") .append(annotation != null ? annotation.scope() : "public") @@ -367,7 +410,7 @@ private void appendMethodHandles(TypeElement type, StringBuilder sb, List toValueLayout(e.asType())) .collect(Collectors.joining(", "))); sb1.append("))).orElse"); - if (annotation != null && annotation.optional()) { + if (defaulted != null) { sb1.append("(null)"); } else { sb1.append("Throw()"); diff --git a/src/main/java/overrun/marshal/Overload.java b/src/main/java/overrun/marshal/Overload.java index 203eea8..06b77f4 100644 --- a/src/main/java/overrun/marshal/Overload.java +++ b/src/main/java/overrun/marshal/Overload.java @@ -19,6 +19,19 @@ import java.lang.annotation.*; /** + * Marks a method as an overload. + *

+ * An overload method keeps {@link String} and array types + * instead of converting them into {@link java.lang.foreign.MemorySegment MemorySegment}. + * It will also invoke another method with the same name or {@linkplain #value() the specified value}. + *

Example

+ *
{@code
+ * void nset(MemorySegment vec);
+ *
+ * @Overload
+ * void set(int[] vec);
+ * }
+ * * @author squid233 * @since 0.1.0 */ @@ -26,5 +39,8 @@ @Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Overload { + /** + * {@return the name of the other method to be overloaded} + */ String value() default ""; } diff --git a/src/main/java/overrun/marshal/Ref.java b/src/main/java/overrun/marshal/Ref.java index c1bca23..64c7f59 100644 --- a/src/main/java/overrun/marshal/Ref.java +++ b/src/main/java/overrun/marshal/Ref.java @@ -19,6 +19,12 @@ import java.lang.annotation.*; /** + * Marks a parameter of an array type that reads the result from the native code. + *

Example

+ *
{@code
+ * void get(@Ref int[] dst);
+ * }
+ * * @author squid233 * @since 0.1.0 */ @@ -26,5 +32,8 @@ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.SOURCE) public @interface Ref { + /** + * {@return {@code true} if the array is nullable; {@code false} otherwise} + */ boolean nullable() default false; } diff --git a/src/main/java/overrun/marshal/package-info.java b/src/main/java/overrun/marshal/package-info.java new file mode 100644 index 0000000..9fe1b9a --- /dev/null +++ b/src/main/java/overrun/marshal/package-info.java @@ -0,0 +1,24 @@ +/* + * MIT License + * + * Copyright (c) 2023 Overrun Organization + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + */ + +/** + * The main package of marshal. + * + * @author squid233 + * @see overrun.marshal.NativeApi + * @since 0.1.0 + */ +package overrun.marshal;