mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-06-12 05:07:46 +02:00
feat(common/util): protobuf utils
This commit is contained in:
@ -0,0 +1,53 @@
|
||||
package me.rhunk.snapenhance.common.util.protobuf
|
||||
|
||||
class GrpcReader(
|
||||
private val buffer: ByteArray
|
||||
) {
|
||||
private val _messages = mutableListOf<ProtoReader>()
|
||||
private val _headers = mutableMapOf<String, String>()
|
||||
|
||||
val headers get() = _headers.toMap()
|
||||
val messages get() = _messages.toList()
|
||||
|
||||
fun read(reader: ProtoReader.() -> Unit) {
|
||||
messages.forEach { message ->
|
||||
message.reader()
|
||||
}
|
||||
}
|
||||
|
||||
private var position: Int = 0
|
||||
|
||||
init {
|
||||
read()
|
||||
}
|
||||
|
||||
private fun readByte() = buffer[position++].toInt()
|
||||
|
||||
private fun readUInt32() = (readByte() and 0xFF) shl 24 or
|
||||
((readByte() and 0xFF) shl 16) or
|
||||
((readByte() and 0xFF) shl 8) or
|
||||
(readByte() and 0xFF)
|
||||
|
||||
private fun read() {
|
||||
while (position < buffer.size) {
|
||||
when (val type = readByte() and 0xFF) {
|
||||
0 -> {
|
||||
val length = readUInt32()
|
||||
val value = buffer.copyOfRange(position, position + length)
|
||||
position += length
|
||||
_messages.add(ProtoReader(value))
|
||||
}
|
||||
128 -> {
|
||||
val length = readUInt32()
|
||||
val rawHeaders = String(buffer.copyOfRange(position, position + length), Charsets.UTF_8)
|
||||
position += length
|
||||
rawHeaders.trim().split("\n").forEach { header ->
|
||||
val (key, value) = header.split(":")
|
||||
_headers[key] = value
|
||||
}
|
||||
}
|
||||
else -> throw Exception("Unknown type $type")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package me.rhunk.snapenhance.common.util.protobuf
|
||||
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
fun ProtoWriter.toGrpcWriter() = GrpcWriter(toByteArray())
|
||||
|
||||
class GrpcWriter(
|
||||
vararg val messages: ByteArray
|
||||
) {
|
||||
private val headers = mutableMapOf<String, String>()
|
||||
|
||||
fun addHeader(key: String, value: String) {
|
||||
headers[key] = value
|
||||
}
|
||||
|
||||
fun toByteArray(): ByteArray {
|
||||
val stream = ByteArrayOutputStream()
|
||||
|
||||
fun writeByte(value: Int) = stream.write(value)
|
||||
fun writeUInt(value: Int) {
|
||||
writeByte(value ushr 24)
|
||||
writeByte(value ushr 16)
|
||||
writeByte(value ushr 8)
|
||||
writeByte(value)
|
||||
}
|
||||
|
||||
messages.forEach { message ->
|
||||
writeByte(0)
|
||||
writeUInt(message.size)
|
||||
stream.write(message)
|
||||
}
|
||||
|
||||
if (headers.isNotEmpty()){
|
||||
val rawHeaders = headers.map { (key, value) -> "$key:$value" }.joinToString("\n")
|
||||
val rawHeadersBytes = rawHeaders.toByteArray(Charsets.UTF_8)
|
||||
writeByte(-128)
|
||||
writeUInt(rawHeadersBytes.size)
|
||||
stream.write(rawHeadersBytes)
|
||||
}
|
||||
|
||||
return stream.toByteArray()
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user