package com.example.whatever.extentions import android.util.Base64 import com.example.whatever.util.CRC16 import java.io.ByteArrayOutputStream import kotlin.experimental.xor fun ByteArray.startsWith(prefix: ByteArray): Boolean { require(this.size >= prefix.size) { "ByteArray is smaller than the prefix." } for (i in prefix.indices) { if (this[i] != prefix[i]) { return false } } return true } fun ByteArray.base64() : String { return Base64.encodeToString(this, Base64.NO_WRAP) } private val hexEncodingTable = byteArrayOf( '0'.toByte(), '1'.toByte(), '2'.toByte(), '3'.toByte(), '4'.toByte(), '5'.toByte(), '6'.toByte(), '7'.toByte(), '8'.toByte(), '9'.toByte(), 'A'.toByte(), 'B'.toByte(), 'C'.toByte(), 'D'.toByte(), 'E'.toByte(), 'F'.toByte() ) fun ByteArray.toHexStrings(space: Boolean = true) : String { val out = ByteArrayOutputStream() try { for (i in 0 until size) { val v: Int = this[i].toInt() and 0xff out.write(hexEncodingTable[v ushr 4].toInt()) out.write(hexEncodingTable[v and 0xf].toInt()) if (space) { out.write(' '.toInt()) } } } catch (e: java.lang.Exception) { throw IllegalStateException("exception encoding Hex string: " + e.message, e) } val bytes = out.toByteArray() return String(bytes) } const val RADIX_62 = 62 /** * 把[from, to) 部分的子数组,转换为以 0-9 a-z A-Z 共 62个字符组成的数字 * * @param from 起始 * @param to 结束(不包含) */ fun ByteArray.to62Num(from: Int, to: Int) : Int { var sum = 0 var scale = 1 for (i in to - 1 downTo from) { sum += from62(this[i]) * scale scale *= RADIX_62 } return sum } /** * 把[from, to) 部分的字节做异或 */ fun ByteArray.xor(from: Int, to: Int) : Byte { var res = this[from] for (i in (from + 1) until to) { res = res xor this[i] } return res } private fun from62(b: Byte): Int { if (b in 0x30..0x39) { return b - 0x30 } if (b in 0x61..0x7a) { return b - 0x57 } if (b in 0x41..0x5a) { return b - 0x1d } throw IllegalArgumentException("$b is not a num char") } /** * 计算 [from, to) 部分的字节做 的 CRC16 校验值 * @return 两字节的校验值 */ fun ByteArray.crc16(from: Int = 0, to: Int = size) : ByteArray { val value = CRC16.crc16(this, from.coerceAtLeast(0), to.coerceAtMost(size)) val c1 = (0xff00 and value shr 8).toByte() val c2 = (0xff and value).toByte() return byteArrayOf(c1, c2) }