Code Snippet
Embed Dependenices without any plugin in Gradle
The simplest way to embed dependencies in Gradle without any plugin
1jar {
2    // Copy from compileClasspath
3    from {
4        // handling duplicate file strategy
5        duplicatesStrategy = DuplicatesStrategy.WARN
6        
7        // copy all files from compileClasspath
8        configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
9    }
10}
Expand variables like {version} in resource file for Gradle
Transform resource file with variables like {version} to real value
1processResources {
2    inputs.property("version", project.version)
3    
4    filesMatching("plugin.yml") {
5        expand("version": project.version)
6    }
7}
Add source jar with Gradle
generate a sources.jar while project build
1// For Gradle 6.0+
2// Require "java" or "java-library" plugin
3java {
4    withSourcesJar()
5}
6
7// For Any Gradle Version
8// no plugin required
9task sourcesJar(type: Jar, dependsOn: jar) {
10    classifier = 'sources'
11    from sourceSets.main.allSource
12}
Equivalent JavaScript Class in Function
Classes are a template for creating objects, built on prototypes. A JavaScript class is a type of function. So you can convert a class to a function.
1// <<< using class syntax >>>
2class Person {
3    constructor(name) {
4        this.name = name;
5    }
6
7    say() {
8        console.log(`Hello, ${this.name}`);
9    }
10}
11
12// <<< using function syntax >>>
13'use strict'; // class syntax is strict mode by default
14
15// call new on function is equivalent to create an object with the function as constructor
16function Person(name) {
17    // constructor cannot be called without 'new'
18    if (!(this instanceof Person)) {
19        throw new TypeError("Class constructor Person cannot be invoked without 'new'");
20    }
21    
22    this.name = name;
23}
24
25// class function is not enumerable by default,
26// so we need to set enumerable to false.
27Object.defineProperty(Person.prototype, 'say', {
28    value: function() {
29        // this must be an 'instance' of Person
30        if (!(this instanceof Person)) {
31            throw new TypeError("function say is not a constructor");
32        }
33        
34        console.log(`Hello, ${this.name}`);
35    },
36    enumerable: false,
37});
Use Collector to merge multiple JSON objects into one
Turn Stream<JsonObject> to single JsonObject
1static Collector<JsonElement, ?, JsonObject> collectAsJsonObject() {
2    return Collector.of(
3            JsonObject::new,
4            (obj, element) -> {
5                if (element.isJsonObject()) {
6                    for (Map.Entry<String, JsonElement> key : element.getAsJsonObject().entrySet()) {
7                        obj.add(key.getKey(), key.getValue());
8                    }
9                }
10            },
11            (obj1, obj2) -> {
12                for (Map.Entry<String, JsonElement> key : obj2.entrySet()) {
13                    obj1.add(key.getKey(), key.getValue());
14                }
15                return obj1;
16            }
17    );
18}
Get all classes under a package
Use guava to get all classes under a package without loading it
1import com.google.common.reflect.ClassPath;
2
3// package filter
4var packageName = "com.trychen.index";
5
6// get all class info
7var classInfos = ClassPath.from(loader)
8    .getAllClasses()
9    .stream()
10    .filter(clazz -> clazz.getPackageName().startsWith(packageName))
11    .collect(Collectors.toSet());
12    
13// load into class (exception may throw)
14var classes = classInfos.stream()
15    .map(ClassPath.ClassInfo::load)
16    .collect(Collectors.toSet());
Read VarInt (variable integer) from DataStream
Variable-width integers, or varints, are at the core of the wire format. They allow encoding unsigned 64-bit integers using anywhere between one and ten bytes, with small values using fewer bytes. Each byte in the varint has a continuation bit that indicates if the byte that follows it is part of the varint.
1static void writeVarInt(DataOutputStream to, int toWrite) throws IOException {
2    while ((toWrite & -128) != 0) {
3        to.writeByte(toWrite & 127 | 128);
4        toWrite >>>= 7;
5    }
6    to.writeByte(toWrite);
7}
8
9static int readVarInt(DataInputStream input) throws IOException {
10    int i = 0;
11    int j = 0;
12    byte b0;
13
14    do {
15        b0 = input.readByte();
16        i |= (b0 & 127) << j++ * 7;
17    }
18    while ((b0 & 128) == 128);
19
20    return i;
21}
Transform string with Minecraft color code to HTML
Generate pure html without css class
1const colors = new Map();
2
3colors.set("a", "#55ff55");
4colors.set("b", "#55ffff");
5colors.set("c", "#ff5555");
6colors.set("d", "#ff55ff");
7colors.set("e", "#ffff55");
8colors.set("f", "#ffffff");
9colors.set("g", "#ddd605");
10colors.set("0", "#000000");
11colors.set("1", "#0000aa");
12colors.set("2", "#00aa00");
13colors.set("3", "#00aaaa");
14colors.set("4", "#aa0000");
15colors.set("5", "#aa00aa");
16colors.set("6", "#ffaa00");
17colors.set("7", "#aaaaaa");
18colors.set("8", "#555555");
19colors.set("9", "#5555ff");
20
21export function convertMinecraftColorToSpan(text: string) {
22    if (!text) return text;
23
24    let result = "";
25    let color = "currentColor";
26    let bold = false;
27    let italic = false;
28    let underline = false;
29    let strikethrough = false;
30    let obfuscated = false;
31
32    let currentSpan = "";
33
34    for (let i = 0; i < text.length; i++) {
35        // Optional & support
36        if (text[i] == "§" || text[i] == "&") {
37            if (i + 1 < text.length) {
38                let c = text[i + 1];
39
40                if (currentSpan) {
41                    result += `<span style="color: ${color};`
42                    if (bold) result += "font-weight: bold;"
43                    if (italic) result += "font-style: italic;"
44                    if (underline) result += "text-decoration: underline;"
45                    if (strikethrough) result += "text-decoration: line-through;"
46                    if (obfuscated) result += "text-shadow: 0 0 0.5em white;"
47                    result += `">${currentSpan}</span>`;
48                    
49                    currentSpan = "";
50                }
51
52                if (c == "r") {
53                    color = "currentColor";
54                    bold = false;
55                    italic = false;
56                    underline = false;
57                    strikethrough = false;
58                    obfuscated = false;
59                } else if (c == "l") {
60                    bold = true;
61                } else if (c == "o") {
62                    italic = true;
63                } else if (c == "n") {
64                    underline = true;
65                } else if (c == "m") {
66                    strikethrough = true;
67                } else if (c == "k") {
68                    obfuscated = true;
69                } else if (colors.has(c)) {
70                    const newColor = colors.get(c);
71                    color = newColor;
72                }
73                i++;
74            }
75        } else if (text[i] == "\n") {
76            currentSpan += "<br>";
77        } else {
78            currentSpan += text[i];
79        }
80    }
81
82    if (currentSpan) {
83        result += `<span style="color: ${color};`
84        if (bold) result += "font-weight: bold;"
85        if (italic) result += "font-style: italic;"
86        if (underline) result += "text-decoration: underline;"
87        if (strikethrough) result += "text-decoration: line-through;"
88        if (obfuscated) result += "text-shadow: 0 0 0.5em white;"
89        result += `">${currentSpan}</span>`;
90    }
91
92    return result;
93}
Using CompletableFuture in Kotlinx.Coroutine
Await the result of CompletableFuture in Kotlinx.Coroutine
1private class ContinuationConsumer<T>(
2    @Volatile @JvmField var cont: Continuation<T>?
3) : BiConsumer<T?, Throwable?> {
4    @Suppress("UNCHECKED_CAST")
5    override fun accept(result: T?, exception: Throwable?) {
6        val cont = this.cont ?: return // atomically read current value unless null
7        if (exception == null) {
8            // the future has completed normally
9            cont.resume(result as T)
10        } else {
11            // the future has completed with an exception, unwrap it to provide consistent view of .await() result and to propagate only original exception
12            cont.resumeWithException((exception as? CompletionException)?.cause ?: exception)
13        }
14    }
15}
16
17/**
18 * Awaits for completion of [CompletionStage] without blocking a thread.
19 *
20 * This suspending function is cancellable.
21 * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
22 * stops waiting for the completion stage and immediately resumes with [CancellationException][kotlinx.coroutines.CancellationException].
23 *
24 * This method is intended to be used with one-shot futures, so on coroutine cancellation the [CompletableFuture] that
25 * corresponds to this [CompletionStage] (see [CompletionStage.toCompletableFuture])
26 * is cancelled. If cancelling the given stage is undesired, `stage.asDeferred().await()` should be used instead.
27 */
28public suspend fun <T> CompletionStage<T>.await(): T {
29    val future = toCompletableFuture() // retrieve the future
30    // fast path when CompletableFuture is already done (does not suspend)
31    if (future.isDone) {
32        try {
33            @Suppress("BlockingMethodInNonBlockingContext")
34            return future.get() as T
35        } catch (e: ExecutionException) {
36            throw e.cause ?: e // unwrap original cause from ExecutionException
37        }
38    }
39    // slow path -- suspend
40    return suspendCancellableCoroutine { cont: CancellableContinuation<T> ->
41        val consumer = ContinuationConsumer(cont)
42        whenComplete(consumer)
43        cont.invokeOnCancellation {
44            future.cancel(false)
45            consumer.cont = null // shall clear reference to continuation to aid GC
46        }
47    }
48}
Print stack trace of an exception in Kotlinx.Coroutine
By default, Kotlinx.Coroutine will not print stack trace of an exception. This snippet will print stack trace of an exception.
1fun CoroutineExceptionHandler(key: String) = kotlinx.coroutines.CoroutineExceptionHandler { _, exception ->
2    logger.error("$key coroutine uncaught exception", exception)
3}
Calculate MD5 of a file in Rust
An example of using md5 and file to calculate MD5 of a file in stream
1use md5::Context;
2use std::path::Path;
3use std::{fs, io};
4
5pub fn calculate_md5(file_path: &Path) -> io::Result<String> {
6    let file = fs::File::open(file_path)?;
7    let mut context = Context::new();
8    let mut buffer = [0; 4096]; // buffer size: 4KB
9
10    let mut reader = io::BufReader::new(file);
11    loop {
12        let bytes_read = reader.read(&mut buffer)?;
13        if bytes_read == 0 {
14            break;
15        }
16        context.consume(&buffer[..bytes_read]);
17    }
18
19    let result = context.compute();
20    Ok(format!("{:x}", result))
21}
Generate random string or bytes in Rust
An example of using create::rand and Iterator to generate random string or bytes
1use rand::{thread_rng, Rng};
2
3pub fn generate_random_string(length: usize) -> String {
4    let charset: &[u8] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
5    let mut rng = thread_rng();
6    let random_string: String = (0..length)
7        .map(|_| {
8            let idx = rng.gen_range(0..charset.len());
9            char::from(charset[idx])
10        })
11        .collect();
12
13    random_string
14}
15
16pub fn generate_random_u8_array(length: usize) -> Vec<u8> {
17    let mut rng = thread_rng();
18    let random_bytes: Vec<u8> = (0..length)
19        .map(|_| rng.gen::<u8>())
20        .collect();
21
22    random_bytes
23}
Unauthorized reproduction of original content on this website is prohibited.