private void storeGistRecord(@NotNull GistRecord<Data> record,
                                 @NotNull VirtualFile file,
                                 @NotNull AttributeOutputStream attributeStream) throws IOException {
      //gist record format: <enumerated projectId:varint>, <gistStamp:int>, <valueKind:byte>, <payload...>?
      //  projectId: varint (enumerated projectId)
      //  gistStamp: int
      //  valueKind: byte (0,1,2)
      //             0: (gist value is null)
      //             1: (gist value is stored inline, in VFS attribute)
      //                payload = gistData: byte[]
      //             2: (gist value is stored in a dedicated file '<HUGE_GIST_DIR>/<fileId>.<gistPathSuffix>')
      //                payload = gistPathSuffix: UTF8 string (as per IOUtil.readUTF)

      attributeStream.writeEnumeratedString(record.projectId);
      attributeStream.writeInt(record.gistStamp);

      String gistFileSuffix = record.externalFileSuffix;

      if (!record.payloadWasChanged) {
        //Fast path for unchanged records -- we already know there to store the payload,
        //     so could skip intermediate buffer and write directly to the attribute
        if (record.payload == null) {
          if (gistFileSuffix != null) {
            //We don't load payload from external files, hence (payload=null & gistFileSuffix!=null)
            // means actual payload is in dedicated file:
            attributeStream.writeByte(VALUE_KIND_IN_DEDICATED_FILE);
            IOUtil.writeUTF(attributeStream, gistFileSuffix);
          }
          else {
            attributeStream.writeByte(VALUE_KIND_NULL);
          }
        }
        else {
          if (record.externalFileSuffix == null) {
            attributeStream.writeByte(VALUE_KIND_INLINE);
            externalizer.save(attributeStream, record.payload);
          }
          else {
            //We do not deserialize payload if it is in an external file, hence if .externalFileSuffix!=null
            //  .payload must be null then
            throw new AssertionError("Bug " + record + ": unchanged record with .payload!=null must have .externalFileSuffix=null");
          }
        }
        return;
      }

      //Changed record with payload=null: fast path
      if (record.payload == null) {
        attributeStream.writeByte(VALUE_KIND_NULL);
        //if huge-file was used previously -> remove the file
        if (gistFileSuffix != null) {
          Path gistPath = dedicatedGistFilePath(file, gistFileSuffix);
          FileUtilRt.deleteRecursively(gistPath);
        }
        return;
      }

      //Changed record with payload!=null: serialise payload into a temporary buffer, check buffer size,
      // and decide there to store payload of that size -- inline in attribute, or in a dedicated file:

      BufferExposingByteArrayOutputStream outputStream = new BufferExposingByteArrayOutputStream();
      DataOutputStream temporaryStream = new DataOutputStream(outputStream);
      externalizer.save(temporaryStream, record.payload);
      temporaryStream.flush();

      if (outputStream.size() <= MAX_GIST_SIZE_TO_STORE_IN_ATTRIBUTES) {
        attributeStream.writeByte(VALUE_KIND_INLINE);
        attributeStream.write(outputStream.getInternalBuffer(), 0, outputStream.size());

        //payload is small enough to inline it: if huge-file was used previously -> remove the file
        if (gistFileSuffix != null) {
          Path gistPath = dedicatedGistFilePath(file, gistFileSuffix);
          FileUtilRt.deleteRecursively(gistPath);
        }
      }
      else {
        attributeStream.writeByte(VALUE_KIND_IN_DEDICATED_FILE);
        if (gistFileSuffix == null) {
          //lets hope random UUID is random enough for avoiding collisions
          gistFileSuffix = UUID.randomUUID().toString();
        }
        IOUtil.writeUTF(attributeStream, gistFileSuffix);

        Path gistPath = dedicatedGistFilePath(file, gistFileSuffix);
        try (DataOutputStream gistFileStream = new DataOutputStream(Files.newOutputStream(gistPath, WRITE, CREATE))) {
          gistFileStream.write(outputStream.getInternalBuffer(), 0, outputStream.size());
        }
      }
    }
private void storeGistRecord(@NotNull GistRecord<Data> record,
                                 @NotNull VirtualFile file,
                                 @NotNull AttributeOutputStream attributeStream)