package bigcache import ( "encoding/binary" "reflect" "unsafe" ) const ( timestampSizeInBytes = 8 // Number of bytes used for timestamp hashSizeInBytes = 8 // Number of bytes used for hash keySizeInBytes = 2 // Number of bytes used for size of entry key headersSizeInBytes = timestampSizeInBytes + hashSizeInBytes + keySizeInBytes // Number of bytes used for all headers ) func wrapEntry(timestamp uint64, hash uint64, key string, entry []byte, buffer *[]byte) []byte { keyLength := len(key) blobLength := len(entry) + headersSizeInBytes + keyLength if blobLength > len(*buffer) { *buffer = make([]byte, blobLength) } blob := *buffer binary.LittleEndian.PutUint64(blob, timestamp) binary.LittleEndian.PutUint64(blob[timestampSizeInBytes:], hash) binary.LittleEndian.PutUint16(blob[timestampSizeInBytes+hashSizeInBytes:], uint16(keyLength)) copy(blob[headersSizeInBytes:], key) copy(blob[headersSizeInBytes+keyLength:], entry) return blob[:blobLength] } func readEntry(data []byte) []byte { length := binary.LittleEndian.Uint16(data[timestampSizeInBytes+hashSizeInBytes:]) // copy on read dst := make([]byte, len(data)-int(headersSizeInBytes+length)) copy(dst, data[headersSizeInBytes+length:]) return dst } func readTimestampFromEntry(data []byte) uint64 { return binary.LittleEndian.Uint64(data) } func readKeyFromEntry(data []byte) string { length := binary.LittleEndian.Uint16(data[timestampSizeInBytes+hashSizeInBytes:]) // copy on read dst := make([]byte, length) copy(dst, data[headersSizeInBytes:headersSizeInBytes+length]) return bytesToString(dst) } func bytesToString(b []byte) string { bytesHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b)) strHeader := reflect.StringHeader{Data: bytesHeader.Data, Len: bytesHeader.Len} return *(*string)(unsafe.Pointer(&strHeader)) } func readHashFromEntry(data []byte) uint64 { return binary.LittleEndian.Uint64(data[timestampSizeInBytes:]) } func resetKeyFromEntry(data []byte) { binary.LittleEndian.PutUint64(data[timestampSizeInBytes:], 0) }