mirror of
https://github.com/mamoe/mirai.git
synced 2025-04-05 07:10:11 +08:00
Implement ByteArrayOp
This commit is contained in:
parent
17430857a8
commit
a1832a4de7
buildSrc/src/main/kotlin
mirai-core-utils/src
commonMain/kotlin
jvmBaseMain/kotlin
nativeMain/kotlin
nativeMainInterop
nativeTest/kotlin
mirai-core/src
commonMain/kotlin
commonTest/kotlin
@ -18,6 +18,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
|
||||
import java.io.File
|
||||
|
||||
private val miraiPlatform = Attribute.of(
|
||||
@ -133,7 +134,8 @@ private fun Project.configureNativeInterop(
|
||||
nativeTargets: MutableList<KotlinNativeTarget>
|
||||
) {
|
||||
if (nativeInteropDir.exists() && nativeInteropDir.isDirectory && nativeInteropDir.resolve("build.rs").exists()) {
|
||||
val crateName = project.name.replace("-", "_")
|
||||
val crateName = project.name.replace("-", "_") + "_i"
|
||||
val kotlinDylibName = project.name.replace("-", "_")
|
||||
|
||||
val headerName = "$crateName.h"
|
||||
val rustLibDir = nativeInteropDir.resolve("target/debug/")
|
||||
@ -149,10 +151,16 @@ private fun Project.configureNativeInterop(
|
||||
sharedLib {
|
||||
linkerOpts("-v")
|
||||
linkerOpts("-L${rustLibDir.absolutePath.replace("\\", "/")}")
|
||||
// linkerOpts("-lmyrust")
|
||||
linkerOpts("-Wl,-undefined,dynamic_lookup") // resolve symbols in runtime
|
||||
// linkerOpts("-lmirai_core_utils_i")
|
||||
linkerOpts("-undefined", "dynamic_lookup")
|
||||
baseName = project.name
|
||||
}
|
||||
getTest(NativeBuildType.DEBUG).apply {
|
||||
linkerOpts("-v")
|
||||
linkerOpts("-L${rustLibDir.absolutePath.replace("\\", "/")}")
|
||||
linkerOpts("-lmirai_core_utils_i")
|
||||
// linkerOpts("-undefined", "dynamic_lookup")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,7 +198,7 @@ private fun Project.configureNativeInterop(
|
||||
val bindgen = tasks.register("bindgen${compilationName.titlecase()}") {
|
||||
group = "mirai"
|
||||
val bindingsPath = nativeInteropDir.resolve("src/bindings.rs")
|
||||
val headerFile = buildDir.resolve("bin/native/debugShared/lib${crateName}_api.h")
|
||||
val headerFile = buildDir.resolve("bin/native/debugShared/lib${kotlinDylibName}_api.h")
|
||||
inputs.files(headerFile)
|
||||
outputs.file(bindingsPath)
|
||||
mustRunAfter(tasks.findByName("linkDebugSharedNative"))
|
||||
@ -239,7 +247,7 @@ private fun Project.configureNativeInterop(
|
||||
"build",
|
||||
"--color", "always",
|
||||
"--all",
|
||||
"--", "--color", "always", "2>&1"
|
||||
// "--", "--color", "always", "2>&1"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -7,28 +7,15 @@
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:JvmMultifileClass
|
||||
@file:JvmName("MiraiUtils")
|
||||
@file:JvmName("ByteArrayOpKt_common")
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import io.ktor.utils.io.core.Closeable
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.jvm.JvmMultifileClass
|
||||
import kotlin.jvm.JvmName
|
||||
|
||||
public expect val DEFAULT_BUFFER_SIZE: Int
|
||||
|
||||
public expect fun ByteArray.unzip(offset: Int = 0, length: Int = size - offset): ByteArray
|
||||
|
||||
|
||||
/**
|
||||
* Localhost 解析
|
||||
*/
|
||||
public expect fun localIpAddress(): String
|
||||
|
||||
public fun String.md5(): ByteArray = toByteArray().md5()
|
||||
|
||||
public expect fun ByteArray.md5(offset: Int = 0, length: Int = size - offset): ByteArray
|
||||
@ -37,24 +24,8 @@ public fun String.sha1(): ByteArray = toByteArray().sha1()
|
||||
|
||||
public expect fun ByteArray.sha1(offset: Int = 0, length: Int = size - offset): ByteArray
|
||||
|
||||
public expect fun ByteArray.gzip(offset: Int = 0, length: Int = size - offset): ByteArray
|
||||
public expect fun ByteArray.ungzip(offset: Int = 0, length: Int = size - offset): ByteArray
|
||||
|
||||
public expect fun ByteArray.gzip(offset: Int = 0, length: Int = size - offset): ByteArray
|
||||
|
||||
public expect fun ByteArray.zip(offset: Int = 0, length: Int = size - offset): ByteArray
|
||||
|
||||
public expect fun availableProcessors(): Int
|
||||
|
||||
public inline fun <C : Closeable, R> C.withUse(block: C.() -> R): R {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return use(block)
|
||||
}
|
||||
|
||||
public inline fun <I : Closeable, O : Closeable, R> I.withOut(output: O, block: I.(output: O) -> R): R {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return use { output.use { block(this, output) } }
|
||||
}
|
||||
public expect fun ByteArray.inflate(offset: Int = 0, length: Int = size - offset): ByteArray
|
||||
public expect fun ByteArray.deflate(offset: Int = 0, length: Int = size - offset): ByteArray
|
@ -18,6 +18,8 @@ import io.ktor.utils.io.*
|
||||
import io.ktor.utils.io.charsets.*
|
||||
import io.ktor.utils.io.core.*
|
||||
import io.ktor.utils.io.core.internal.*
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.jvm.JvmMultifileClass
|
||||
import kotlin.jvm.JvmName
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
@ -27,6 +29,20 @@ public val EMPTY_BYTE_ARRAY: ByteArray = ByteArray(0)
|
||||
public val DECRYPTER_16_ZERO: ByteArray = ByteArray(16)
|
||||
public val KEY_16_ZEROS: ByteArray = ByteArray(16)
|
||||
|
||||
public inline fun <C : Closeable, R> C.withUse(block: C.() -> R): R {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return use(block)
|
||||
}
|
||||
|
||||
public inline fun <I : Closeable, O : Closeable, R> I.withOut(output: O, block: I.(output: O) -> R): R {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return use { output.use { block(this, output) } }
|
||||
}
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
public inline fun <R> ByteReadPacket.useBytes(
|
||||
n: Int = remaining.toInt(),//not that safe but adequate
|
||||
|
@ -166,4 +166,12 @@ public inline fun <reified T> isSameType(thisObject: T, other: Any?): Boolean {
|
||||
if (other == null) return false
|
||||
if (other !is T) return false
|
||||
return isSameClass(thisObject, other)
|
||||
}
|
||||
}
|
||||
|
||||
public expect fun availableProcessors(): Int
|
||||
|
||||
|
||||
/**
|
||||
* Localhost 解析
|
||||
*/
|
||||
public expect fun localIpAddress(): String
|
||||
|
@ -12,11 +12,9 @@
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.net.Inet4Address
|
||||
import java.security.MessageDigest
|
||||
import java.util.zip.Deflater
|
||||
import java.util.zip.GZIPInputStream
|
||||
@ -25,7 +23,7 @@ import java.util.zip.Inflater
|
||||
|
||||
public actual val DEFAULT_BUFFER_SIZE: Int get() = kotlin.io.DEFAULT_BUFFER_SIZE
|
||||
|
||||
public actual fun ByteArray.unzip(offset: Int, length: Int): ByteArray {
|
||||
public actual fun ByteArray.inflate(offset: Int, length: Int): ByteArray {
|
||||
checkOffsetAndLength(offset, length)
|
||||
if (length == 0) return ByteArray(0)
|
||||
|
||||
@ -44,10 +42,6 @@ public actual fun ByteArray.unzip(offset: Int, length: Int): ByteArray {
|
||||
}
|
||||
}
|
||||
|
||||
public actual fun localIpAddress(): String = runCatching {
|
||||
Inet4Address.getLocalHost().hostAddress
|
||||
}.getOrElse { "192.168.1.123" }
|
||||
|
||||
public fun InputStream.md5(): ByteArray {
|
||||
return digest("md5")
|
||||
}
|
||||
@ -104,7 +98,7 @@ public actual fun ByteArray.gzip(offset: Int, length: Int): ByteArray {
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
public actual fun ByteArray.zip(offset: Int, length: Int): ByteArray {
|
||||
public actual fun ByteArray.deflate(offset: Int, length: Int): ByteArray {
|
||||
checkOffsetAndLength(offset, length)
|
||||
if (length == 0) return ByteArray(0)
|
||||
|
||||
@ -117,4 +111,3 @@ public actual fun ByteArray.zip(offset: Int, length: Int): ByteArray {
|
||||
}
|
||||
}
|
||||
|
||||
public actual fun availableProcessors(): Int = Runtime.getRuntime().availableProcessors()
|
@ -9,6 +9,14 @@
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import java.net.Inet4Address
|
||||
|
||||
internal actual fun isSameClassPlatform(object1: Any, object2: Any): Boolean {
|
||||
return object1.javaClass == object2.javaClass
|
||||
}
|
||||
}
|
||||
|
||||
public actual fun localIpAddress(): String = runCatching {
|
||||
Inet4Address.getLocalHost().hostAddress
|
||||
}.getOrElse { "192.168.1.123" }
|
||||
|
||||
public actual fun availableProcessors(): Int = Runtime.getRuntime().availableProcessors()
|
54
mirai-core-utils/src/nativeMain/kotlin/ByteArrayOp.kt
Normal file
54
mirai-core-utils/src/nativeMain/kotlin/ByteArrayOp.kt
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("RedundantVisibilityModifier")
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import interop.*
|
||||
import kotlinx.cinterop.*
|
||||
import platform.posix.free
|
||||
import platform.posix.uint8_tVar
|
||||
|
||||
|
||||
public actual val DEFAULT_BUFFER_SIZE: Int get() = 8192
|
||||
|
||||
public actual fun ByteArray.md5(offset: Int, length: Int): ByteArray = callImpl(::mirai_crypto_md5, offset, length)
|
||||
public actual fun ByteArray.sha1(offset: Int, length: Int): ByteArray = callImpl(::mirai_crypto_sha1, offset, length)
|
||||
|
||||
public actual fun ByteArray.gzip(offset: Int, length: Int): ByteArray = callImpl(::mirai_crypto_gzip, offset, length)
|
||||
public actual fun ByteArray.ungzip(offset: Int, length: Int): ByteArray =
|
||||
callImpl(::mirai_crypto_ungzip, offset, length)
|
||||
|
||||
public actual fun ByteArray.deflate(offset: Int, length: Int): ByteArray =
|
||||
callImpl(::mirai_crypto_deflate, offset, length)
|
||||
|
||||
public actual fun ByteArray.inflate(offset: Int, length: Int): ByteArray =
|
||||
callImpl(::mirai_crypto_inflate, offset, length)
|
||||
|
||||
|
||||
private fun ByteArray.callImpl(
|
||||
fn: (CValuesRef<uint8_tVar>, UInt, CValuesRef<SizedByteArray>) -> Boolean,
|
||||
offset: Int,
|
||||
length: Int
|
||||
): ByteArray {
|
||||
checkOffsetAndLength(offset, length)
|
||||
|
||||
memScoped {
|
||||
val r = alloc<SizedByteArray>()
|
||||
if (!fn(toCValues().ptr.reinterpret<uint8_tVar>().plus(offset)!!, length.toUInt(), r.ptr)) {
|
||||
throw IllegalStateException("Failed platform implementation call")
|
||||
}
|
||||
try {
|
||||
return r.arr?.readBytes(r.size.toInt())!!
|
||||
} finally {
|
||||
free(r.arr)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("RedundantVisibilityModifier")
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
|
||||
public actual fun ByteArray.unzip(offset: Int, length: Int): ByteArray {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
public actual fun localIpAddress(): String = "192.168.1.123"
|
||||
|
||||
|
||||
public actual fun ByteArray.md5(offset: Int, length: Int): ByteArray {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
public actual val DEFAULT_BUFFER_SIZE: Int get() = 8192
|
||||
|
||||
public actual fun ByteArray.sha1(offset: Int, length: Int): ByteArray {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
public actual fun ByteArray.ungzip(offset: Int, length: Int): ByteArray {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
public actual fun ByteArray.gzip(offset: Int, length: Int): ByteArray {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
public actual fun ByteArray.zip(offset: Int, length: Int): ByteArray {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
public actual fun availableProcessors(): Int {
|
||||
TODO("Not yet implemented")
|
||||
}
|
@ -9,6 +9,6 @@
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
internal actual fun isSameClassPlatform(object1: Any, object2: Any): Boolean {
|
||||
return object1::class == object2::class
|
||||
public fun symbolNotFound(name: String): Nothing {
|
||||
throw IllegalStateException("Symbol '$name' not found.")
|
||||
}
|
22
mirai-core-utils/src/nativeMain/kotlin/StandardUtils.kt
Normal file
22
mirai-core-utils/src/nativeMain/kotlin/StandardUtils.kt
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import platform.posix._SC_NPROCESSORS_ONLN
|
||||
import platform.posix.sysconf
|
||||
|
||||
|
||||
public actual fun localIpAddress(): String = "192.168.1.123"
|
||||
|
||||
public actual fun availableProcessors(): Int = sysconf(_SC_NPROCESSORS_ONLN).toInt()
|
||||
|
||||
internal actual fun isSameClassPlatform(object1: Any, object2: Any): Boolean {
|
||||
return object1::class == object2::class
|
||||
}
|
8
mirai-core-utils/src/nativeMainInterop/.gitignore
vendored
Normal file
8
mirai-core-utils/src/nativeMainInterop/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
myrust.h
|
||||
|
||||
*.iml
|
||||
|
||||
src/bindings.rs
|
||||
/*.h
|
18
mirai-core-utils/src/nativeMainInterop/Cargo.toml
Normal file
18
mirai-core-utils/src/nativeMainInterop/Cargo.toml
Normal file
@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "mirai_core_utils_i"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
md5 = "0.7.0"
|
||||
sha1 = "0.10.1"
|
||||
flate2 = "1.0.23"
|
||||
libc = "0.2.126"
|
||||
|
||||
[lib]
|
||||
name = "mirai_core_utils_i"
|
||||
crate-type = ["cdylib"] # Creates dynamic lib
|
||||
# crate-type = ["staticlib"] # Creates static lib
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = "0.53.1"
|
||||
cbindgen = "0.20.0"
|
32
mirai-core-utils/src/nativeMainInterop/build.rs
Normal file
32
mirai-core-utils/src/nativeMainInterop/build.rs
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
extern crate bindgen;
|
||||
extern crate cbindgen;
|
||||
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use cbindgen::Config;
|
||||
use cbindgen::Language::C;
|
||||
|
||||
fn main() {
|
||||
// let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
|
||||
// cbindgen::Builder::new()
|
||||
// .with_crate(crate_dir)
|
||||
// .with_language(C)
|
||||
// .generate()
|
||||
// .expect("Unable to generate bindings")
|
||||
// .write_to_file("nativeInterop.h");
|
||||
|
||||
|
||||
println!("cargo:rustc-link-search=../../build/bin/native/debugShared");
|
||||
println!("cargo:rustc-link-lib=mirai_core_utils");
|
||||
}
|
10
mirai-core-utils/src/nativeMainInterop/cbindgen.toml
Normal file
10
mirai-core-utils/src/nativeMainInterop/cbindgen.toml
Normal file
@ -0,0 +1,10 @@
|
||||
# This is a template cbindgen.toml file with all of the default values.
|
||||
# Some values are commented out because their absence is the real default.
|
||||
#
|
||||
# See https://github.com/eqrion/cbindgen/blob/master/docs.md#cbindgentoml
|
||||
# for detailed documentation of every option here.
|
||||
|
||||
|
||||
|
||||
language = "C"
|
||||
|
0
mirai-core-utils/src/nativeMainInterop/interop.def
Normal file
0
mirai-core-utils/src/nativeMainInterop/interop.def
Normal file
125
mirai-core-utils/src/nativeMainInterop/src/crypto.rs
Normal file
125
mirai-core-utils/src/nativeMainInterop/src/crypto.rs
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
use std::io::{BufReader, Read, Write};
|
||||
|
||||
use flate2::Compression;
|
||||
use flate2::write::{DeflateDecoder, DeflateEncoder, GzDecoder, GzEncoder, ZlibDecoder, ZlibEncoder};
|
||||
use libc::{malloc, read, size_t};
|
||||
use sha1::{Digest, Sha1};
|
||||
use sha1::digest::{Output, OutputSizeUser};
|
||||
use sha1::digest::generic_array::GenericArray;
|
||||
|
||||
#[no_mangle]
|
||||
#[repr(C)]
|
||||
pub struct SizedByteArray {
|
||||
arr: *mut u8,
|
||||
size: u32,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mirai_crypto_md5(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
|
||||
let data = unsafe { std::slice::from_raw_parts(data, len as usize) };
|
||||
let result = md5::compute(data);
|
||||
let size = 16;
|
||||
let mut memory = malloc(size).cast();
|
||||
memory.copy_from(result.as_ptr(), size);
|
||||
|
||||
ret.arr = memory;
|
||||
ret.size = size as u32;
|
||||
return true;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mirai_crypto_sha1(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
|
||||
let data = unsafe { std::slice::from_raw_parts(data, len as usize) };
|
||||
let mut hasher = Sha1::new();
|
||||
hasher.update(data);
|
||||
let result = hasher.finalize();
|
||||
let size = 16;
|
||||
let mut memory = malloc(size).cast();
|
||||
memory.copy_from(result.as_ptr(), size);
|
||||
|
||||
ret.arr = memory;
|
||||
ret.size = size as u32;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mirai_crypto_gzip(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
|
||||
let data = unsafe { std::slice::from_raw_parts(data, len as usize) };
|
||||
let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
|
||||
|
||||
let result = encoder.write_all(data).and_then(|_| { encoder.finish() });
|
||||
if result.is_err() { return false; }
|
||||
let result = result.unwrap();
|
||||
|
||||
let size = result.len();
|
||||
let mut memory = malloc(size).cast();
|
||||
memory.copy_from(result.as_ptr(), size);
|
||||
|
||||
ret.arr = memory;
|
||||
ret.size = size as u32;
|
||||
return true;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mirai_crypto_ungzip(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
|
||||
let data = unsafe { std::slice::from_raw_parts(data, len as usize) };
|
||||
let mut encoder = GzDecoder::new(Vec::new());
|
||||
|
||||
let result = encoder.write_all(data).and_then(|_| { encoder.finish() });
|
||||
if result.is_err() { return false; }
|
||||
let result = result.unwrap();
|
||||
|
||||
let size = result.len();
|
||||
let mut memory = malloc(size).cast();
|
||||
memory.copy_from(result.as_ptr(), size);
|
||||
|
||||
ret.arr = memory;
|
||||
ret.size = size as u32;
|
||||
return true;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mirai_crypto_deflate(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
|
||||
let data = unsafe { std::slice::from_raw_parts(data, len as usize) };
|
||||
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
|
||||
|
||||
let result = encoder.write_all(data).and_then(|_| { encoder.finish() });
|
||||
if result.is_err() { return false; }
|
||||
let result = result.unwrap();
|
||||
|
||||
let size = result.len();
|
||||
let mut memory = malloc(size).cast();
|
||||
memory.copy_from(result.as_ptr(), size);
|
||||
|
||||
ret.arr = memory;
|
||||
ret.size = size as u32;
|
||||
return true;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mirai_crypto_inflate(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool {
|
||||
let data = unsafe { std::slice::from_raw_parts(data, len as usize) };
|
||||
let mut encoder = ZlibDecoder::new(Vec::new());
|
||||
|
||||
let result = encoder.write_all(data).and_then(|_| { encoder.finish() });
|
||||
if result.is_err() { return false; }
|
||||
let result = result.unwrap();
|
||||
|
||||
let size = result.len();
|
||||
let mut memory = malloc(size).cast();
|
||||
memory.copy_from(result.as_ptr(), size);
|
||||
|
||||
ret.arr = memory;
|
||||
ret.size = size as u32;
|
||||
return true;
|
||||
}
|
17
mirai-core-utils/src/nativeMainInterop/src/lib.rs
Normal file
17
mirai-core-utils/src/nativeMainInterop/src/lib.rs
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
extern crate flate2;
|
||||
extern crate libc;
|
||||
extern crate sha1;
|
||||
|
||||
/// cbindgen:ignore
|
||||
mod bindings;
|
||||
mod crypto;
|
||||
|
110
mirai-core-utils/src/nativeTest/kotlin/CryptoTest.kt
Normal file
110
mirai-core-utils/src/nativeTest/kotlin/CryptoTest.kt
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import kotlin.random.Random
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertContentEquals
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class CryptoTest {
|
||||
|
||||
@Test
|
||||
fun testAvailableProcessors() {
|
||||
val processors = availableProcessors()
|
||||
assertTrue(processors.toString()) { processors > 0 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMd5() {
|
||||
val str = getRandomString(10, Random(1))
|
||||
println(str)
|
||||
val hash = str.md5()
|
||||
assertContentEquals(
|
||||
"30 3B 36 B3 42 00 39 E2 EC 18 22 79 10 32 05 48".hexToBytes(),
|
||||
hash,
|
||||
message = hash.toUHexString()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMd5WithOffset() {
|
||||
val str = getRandomString(10, Random(1))
|
||||
println(str)
|
||||
val hash = (byteArrayOf(1) + str.toByteArray()).md5(1)
|
||||
assertContentEquals(
|
||||
"30 3B 36 B3 42 00 39 E2 EC 18 22 79 10 32 05 48".hexToBytes(),
|
||||
hash,
|
||||
message = hash.toUHexString()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSha1() {
|
||||
val str = getRandomString(10, Random(1))
|
||||
println(str)
|
||||
val hash = str.sha1()
|
||||
assertContentEquals(
|
||||
"54 98 CD 62 6C DE E3 9B 96 D4 34 5E 13 51 48 BB".hexToBytes(),
|
||||
hash,
|
||||
message = hash.toUHexString()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDeflate() {
|
||||
val str = "qGnJ1RrFC9"
|
||||
println(str)
|
||||
val hash = str.toByteArray().deflate()
|
||||
assertContentEquals(
|
||||
"78 9C 2B 74 CF F3 32 0C 2A 72 73 B6 04 00 12 82 03 28".hexToBytes(),
|
||||
hash,
|
||||
message = hash.toUHexString()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testInflate() {
|
||||
val result =
|
||||
"78 9C 2B 74 CF F3 32 0C 2A 72 73 B6 04 00 12 82 03 28".hexToBytes()
|
||||
.inflate().decodeToString()
|
||||
assertEquals(
|
||||
"qGnJ1RrFC9",
|
||||
result,
|
||||
message = result
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGzip() {
|
||||
val str = "qGnJ1RrFC9"
|
||||
println(str)
|
||||
val hash = str.toByteArray().gzip()
|
||||
assertContentEquals(
|
||||
"1F 8B 08 00 00 00 00 00 00 FF 2B 74 CF F3 32 0C 2A 72 73 B6 04 00 A8 35 6D D9 0A 00 00 00".hexToBytes(),
|
||||
hash,
|
||||
message = hash.toUHexString()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUnGzip() {
|
||||
val result =
|
||||
"1F 8B 08 00 00 00 00 00 00 FF 2B 74 CF F3 32 0C 2A 72 73 B6 04 00 A8 35 6D D9 0A 00 00 00".hexToBytes()
|
||||
.ungzip().decodeToString()
|
||||
assertEquals(
|
||||
"qGnJ1RrFC9",
|
||||
result,
|
||||
message = result
|
||||
)
|
||||
}
|
||||
}
|
@ -23,10 +23,10 @@ import net.mamoe.mirai.internal.message.protocol.encode.MessageEncoderContext.Co
|
||||
import net.mamoe.mirai.internal.message.runWithBugReport
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import net.mamoe.mirai.utils.deflate
|
||||
import net.mamoe.mirai.utils.hexToBytes
|
||||
import net.mamoe.mirai.utils.inflate
|
||||
import net.mamoe.mirai.utils.toUHexString
|
||||
import net.mamoe.mirai.utils.unzip
|
||||
import net.mamoe.mirai.utils.zip
|
||||
|
||||
/**
|
||||
* Handles:
|
||||
@ -50,7 +50,7 @@ internal class RichMessageProtocol : MessageProtocol() {
|
||||
private class Encoder : MessageEncoder<RichMessage> {
|
||||
override suspend fun MessageEncoderContext.process(data: RichMessage) {
|
||||
markAsConsumed()
|
||||
val content = data.content.toByteArray().zip()
|
||||
val content = data.content.toByteArray().deflate()
|
||||
var longTextResId: String? = null
|
||||
when (data) {
|
||||
is ForwardMessageInternal -> {
|
||||
@ -127,7 +127,7 @@ internal class RichMessageProtocol : MessageProtocol() {
|
||||
{ "resId=" + lightApp.msgResid + "data=" + lightApp.data.toUHexString() }) {
|
||||
when (lightApp.data[0].toInt()) {
|
||||
0 -> lightApp.data.decodeToString(startIndex = 1)
|
||||
1 -> lightApp.data.unzip(1).decodeToString()
|
||||
1 -> lightApp.data.inflate(1).decodeToString()
|
||||
else -> error("unknown compression flag=${lightApp.data[0]}")
|
||||
}
|
||||
}
|
||||
@ -146,7 +146,7 @@ internal class RichMessageProtocol : MessageProtocol() {
|
||||
val content = runWithBugReport("解析 richMsg", { richMsg.template1.toUHexString() }) {
|
||||
when (richMsg.template1[0].toInt()) {
|
||||
0 -> richMsg.template1.decodeToString(startIndex = 1)
|
||||
1 -> richMsg.template1.unzip(1).decodeToString()
|
||||
1 -> richMsg.template1.inflate(1).decodeToString()
|
||||
else -> error("unknown compression flag=${richMsg.template1[0]}")
|
||||
}
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ internal class PacketCodecImpl : PacketCodec {
|
||||
1 -> {
|
||||
input.discardExact(4)
|
||||
input.useBytes { data, length ->
|
||||
data.unzip(0, length).let {
|
||||
data.inflate(0, length).let {
|
||||
val size = it.toInt()
|
||||
if (size == it.size || size == it.size + 4) {
|
||||
it.toReadPacket(offset = 4)
|
||||
|
@ -20,8 +20,8 @@ import net.mamoe.mirai.internal.utils.io.ProtoBuf
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.loadAs
|
||||
import net.mamoe.mirai.internal.utils.structureToStringIfAvailable
|
||||
import net.mamoe.mirai.utils.EMPTY_BYTE_ARRAY
|
||||
import net.mamoe.mirai.utils.inflate
|
||||
import net.mamoe.mirai.utils.isSameType
|
||||
import net.mamoe.mirai.utils.unzip
|
||||
import kotlin.jvm.JvmField
|
||||
|
||||
@Serializable
|
||||
@ -558,7 +558,7 @@ internal class ImMsgBody : ProtoBuf {
|
||||
|
||||
return when (byteArray[0].toInt()) {
|
||||
0 -> byteArrayOf(0) + byteArray.decodeToString(startIndex = 1).toByteArray()
|
||||
1 -> byteArrayOf(0) + byteArray.unzip(offset = 1).decodeToString().toByteArray()
|
||||
1 -> byteArrayOf(0) + byteArray.inflate(offset = 1).decodeToString().toByteArray()
|
||||
else -> error("unknown compression flag=${byteArray[0]}")
|
||||
}
|
||||
}
|
||||
|
@ -11,10 +11,10 @@ package net.mamoe.mirai.internal
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import net.mamoe.mirai.internal.test.AbstractTest
|
||||
import net.mamoe.mirai.utils.deflate
|
||||
import net.mamoe.mirai.utils.gzip
|
||||
import net.mamoe.mirai.utils.inflate
|
||||
import net.mamoe.mirai.utils.ungzip
|
||||
import net.mamoe.mirai.utils.unzip
|
||||
import net.mamoe.mirai.utils.zip
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@ -22,7 +22,7 @@ internal class PlatformUtilsTest : AbstractTest() {
|
||||
|
||||
@Test
|
||||
fun testZip() {
|
||||
assertEquals("test", "test".toByteArray().zip().unzip().decodeToString())
|
||||
assertEquals("test", "test".toByteArray().deflate().inflate().decodeToString())
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
Reference in New Issue
Block a user