Closed hykilpikonna closed 1 year ago
You can try com.github.luben.zstd.util.Native.load()
and catch exceptions: if it throws, the platform is not supported.
I can't import the Zstd class without throwing exceptions on unsupported platforms, so detecting support this way doesn't really do anything (i.e. I still have to import the Zstd class to use it). I ended up using reflections to solve this issue...
package org.hydev.mcpm.utils;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Utility for Zstd-jni
*
* @author Azalea (https://github.com/hykilpikonna)
* @since 2022-11-22
*/
public class ZstdUtils
{
public static final ReflectedZstd zstd;
/**
* Reflected zstd class
*
* @param cl Class object
* @param decompress decompress(byte[], int) method
* @param decompressedSize decompressedSize(byte[]) method
* @param compress compress(byte[]) method
*/
public record ReflectedZstd(Class<?> cl, Method decompress, Method decompressedSize, Method compress) { }
/**
* Get zstd class
*
* @return Zstd class if usable, null otherwise
*/
private static @Nullable ReflectedZstd getZstdClass()
{
try
{
var cl = Class.forName("com.github.luben.zstd.Zstd");
var decompress = cl.getMethod("decompress", byte[].class, int.class);
var decompressedSize = cl.getMethod("decompressedSize", byte[].class);
var compress = cl.getMethod("compress", byte[].class);
return new ReflectedZstd(cl, decompress, decompressedSize, compress);
}
catch (Throwable e)
{
// Any exception here would mean that it isn't supported
return null;
}
}
static
{
zstd = getZstdClass();
}
/**
* Check if zstd is supported on the current platform
*
* @return true if supported
*/
public static boolean isSupported()
{
return zstd != null;
}
/**
* Compress zstd using reflection
*
* @param content Plain text content
* @return Zstd compressed content
*/
public static byte[] compress(byte[] content) throws ZstdException
{
if (!isSupported()) throw new ZstdNotSupported();
try
{
return (byte[]) zstd.compress.invoke(null, (Object) content);
}
catch (IllegalAccessException e)
{
// This would never happen
throw new RuntimeException(e);
}
catch (InvocationTargetException e)
{
// This would be when zstd has some errors
throw new ZstdException(e);
}
}
/**
* Decompress zstd using reflection
*
* @param zst Zstd compressed content
* @return Plain text content
*/
public static byte[] decompress(byte[] zst) throws ZstdException
{
if (!isSupported()) throw new ZstdNotSupported();
try
{
return (byte[]) zstd.decompress.invoke(null, zst,
((Long) zstd.decompressedSize.invoke(null, (Object) zst)).intValue());
}
catch (IllegalAccessException e)
{
// This would never happen
throw new RuntimeException(e);
}
catch (InvocationTargetException e)
{
// This would be when zstd has some errors
throw new ZstdException(e);
}
}
}
Good that you found how to do that.
I want to enable compression if the current platform is supported by zstd-jni. How can I check?