docs: @Override
     public long create(WrappedBytes key, WrappedBytes value, Metadata metadata) {
        byte type;
        boolean shouldWriteMetadataSize = false;
        byte[] metadataBytes;
        if (metadata instanceof EmbeddedMetadata) {
           EntryVersion version = metadata.version();
           byte[] versionBytes;
           if (version != null) {
              type = HAS_VERSION;
              shouldWriteMetadataSize = true;
              try {
                 versionBytes = marshaller.objectToByteBuffer(version);
              } catch (IOException | InterruptedException e) {
                 throw new CacheException(e);
              }
           } else {
              type = 0;
              versionBytes = Util.EMPTY_BYTE_ARRAY;
           }
  
           long lifespan = metadata.lifespan();
           long maxIdle = metadata.maxIdle();
  
           if (lifespan < 0 && maxIdle < 0) {
              type |= IMMORTAL;
              metadataBytes = versionBytes;
           } else if (lifespan > -1 && maxIdle < 0) {
              type |= MORTAL;
              metadataBytes = new byte[16 + versionBytes.length];
              Bits.putLong(metadataBytes, 0, lifespan);
              Bits.putLong(metadataBytes, 8, timeService.wallClockTime());
              System.arraycopy(versionBytes, 0, metadataBytes, 16, versionBytes.length);
           } else if (lifespan < 0 && maxIdle > -1) {
              type |= TRANSIENT;
              metadataBytes = new byte[16 + versionBytes.length];
              Bits.putLong(metadataBytes, 0, maxIdle);
              Bits.putLong(metadataBytes, 8, timeService.wallClockTime());
              System.arraycopy(versionBytes, 0, metadataBytes, 16, versionBytes.length);
           } else {
              type |= TRANSIENT_MORTAL;
              metadataBytes = new byte[32 + versionBytes.length];
              Bits.putLong(metadataBytes, 0, lifespan);
              Bits.putLong(metadataBytes, 8, maxIdle);
              long time = timeService.wallClockTime();
              Bits.putLong(metadataBytes, 16, time);
              Bits.putLong(metadataBytes, 24, time);
              System.arraycopy(versionBytes, 0, metadataBytes, 32, versionBytes.length);
           }
        } else {
           type = CUSTOM;
           shouldWriteMetadataSize = true;
           try {
              metadataBytes = marshaller.objectToByteBuffer(metadata);
           } catch (IOException | InterruptedException e) {
              throw new CacheException(e);
           }
        }
        int keySize = key.getLength();
        int metadataSize = metadataBytes.length;
        int valueSize = value.getLength();
  
        // Eviction requires 2 additional pointers at the beginning
        int offset = evictionEnabled ? 16 : 0;
        // Next 8 is for linked pointer to next address
        long totalSize = offset + 8 + HEADER_LENGTH +
              // If the type has a version or is custom we have to add 4 more bytes for an int to include that
              (shouldWriteMetadataSize ? 4 : 0)
              + keySize + metadataSize + valueSize;
        long memoryAddress = allocator.allocate(totalSize);
  
        // Write the empty linked address pointer first
        MEMORY.putLong(memoryAddress, offset, 0);
        offset += 8;
  
        MEMORY.putByte(memoryAddress, offset, type);
        offset += 1;
        MEMORY.putInt(memoryAddress, offset, key.hashCode());
        offset += 4;
        MEMORY.putInt(memoryAddress, offset, key.getLength());
        offset += 4;
        if (shouldWriteMetadataSize) {
           MEMORY.putInt(memoryAddress, offset, metadataBytes.length);
           offset += 4;
        }
        MEMORY.putInt(memoryAddress, offset, value.getLength());
        offset += 4;
  
        MEMORY.putBytes(key.getBytes(), key.backArrayOffset(), memoryAddress, offset, keySize);
        offset += keySize;
  
        MEMORY.putBytes(metadataBytes, 0, memoryAddress, offset, metadataSize);
        offset += metadataSize;
  
        MEMORY.putBytes(value.getBytes(), value.backArrayOffset(), memoryAddress, offset, valueSize);
        offset += valueSize;
  
        assert offset == totalSize;
  
        return memoryAddress;
     }