All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mb.pie.store.lmdb.Serialize.kt Maven / Gradle / Ivy

There is a newer version: 0.3.0
Show newest version
package mb.pie.store.lmdb

import mb.pie.api.Logger
import java.io.*
import java.nio.ByteBuffer
import java.security.MessageDigest
import java.util.*


@Suppress("NOTHING_TO_INLINE")
inline fun  T.serialize(): ByteArray {
  ByteArrayOutputStream().use {
    ObjectOutputStream(it).use {
      it.writeObject(this)
    }
    // OPTO: copies bytes, not efficient
    return it.toByteArray()
  }
}

@Suppress("NOTHING_TO_INLINE")
inline fun ByteArray.hash(): ByteArray {
  val digest = MessageDigest.getInstance("SHA-1")
  return digest.digest(this)
}

@Suppress("NOTHING_TO_INLINE")
inline fun  T.serializeAndHash(): SerializedAndHashed {
  val serialized = this.serialize()
  val hashed = serialized.hash()
  return SerializedAndHashed(serialized, hashed)
}

data class SerializedAndHashed(val serialized: ByteArray, val hashed: ByteArray) {
  override fun equals(other: Any?): Boolean {
    if(this === other) return true
    if(javaClass != other?.javaClass) return false

    other as SerializedAndHashed

    if(!Arrays.equals(serialized, other.serialized)) return false
    if(!Arrays.equals(hashed, other.hashed)) return false

    return true
  }

  override fun hashCode(): Int {
    var result = Arrays.hashCode(serialized)
    result = 31 * result + Arrays.hashCode(hashed)
    return result
  }
}


fun  Buf.deserialize(logger: Logger): Deserialized {
  ByteBufferBackedInputStream(this).use {
    ObjectInputStream(it).use {
      return try {
        @Suppress("UNCHECKED_CAST")
        val deserialized = it.readObject() as T
        Deserialized(deserialized)
      } catch(e: ClassNotFoundException) {
        logger.error("Deserialization failed", e)
        Deserialized()
      } catch(e: IOException) {
        logger.error("Deserialization failed", e)
        Deserialized()
      }
    }
  }
}

data class Deserialized(val deserialized: R, val failed: Boolean) {
  constructor(deserialized: R) : this(deserialized, false)
  @Suppress("UNCHECKED_CAST")
  constructor() : this(null as R, true)
}

@Suppress("NOTHING_TO_INLINE")
inline fun  Deserialized?.orElse(default: R): R {
  return if(this == null || this.failed) {
    default
  } else {
    this.deserialized
  }
}

inline fun  Deserialized?.mapOrElse(default: RR, func: (R) -> RR): RR {
  return if(this == null || this.failed) {
    default
  } else {
    func(this.deserialized)
  }
}

private class ByteBufferBackedInputStream(private val buf: ByteBuffer) : InputStream() {
  @Throws(IOException::class)
  override fun read(): Int {
    if(!buf.hasRemaining()) {
      return -1
    }
    return buf.get().toInt() and 0xFF
  }

  @Throws(IOException::class)
  override fun read(bytes: ByteArray, offset: Int, length: Int): Int {
    if(!buf.hasRemaining()) {
      return -1
    }

    val minLength = Math.min(length, buf.remaining())
    buf.get(bytes, offset, minLength)
    return minLength
  }
}






© 2015 - 2024 Weber Informatics LLC | Privacy Policy