public void readFrom(@NotNull DataInputStream stream,
                       @NotNull DataExternalizer<? extends Value> externalizer,
                       @NotNull ValueContainerInputRemapping remapping) throws IOException {
    FileId2ValueMapping<Value> mapping = null;

    while (stream.available() > 0) {
      final int valueCount = DataInputOutputUtil.readINT(stream);
      if (valueCount < 0) {
        // ChangeTrackingValueContainer marked inputId as invalidated, see ChangeTrackingValueContainer.saveTo
        @NotNull Object inputIds = remapping.remap(-valueCount);

        if (mapping == null && size() > NUMBER_OF_VALUES_THRESHOLD) { // avoid O(NumberOfValues)
          mapping = new FileId2ValueMapping<>(this);
        }

        boolean doCompact = false;
        if (inputIds instanceof int[]) {
          for (int inputId : (int[])inputIds) {
            doCompact |= removeValue(mapping, inputId);
          }
        }
        else {
          int inputId = (int)inputIds;
          doCompact = removeValue(mapping, inputId);
        }

        if (doCompact) setNeedsCompacting(true);
      }
      else {
        for (int valueIdx = 0; valueIdx < valueCount; valueIdx++) {
          final Value value = externalizer.read(stream);
          int idCountOrSingleValue = DataInputOutputUtil.readINT(stream);

          if (idCountOrSingleValue > 0) {
            int singleId = idCountOrSingleValue;
            @NotNull Object inputIds = remapping.remap(singleId);

            if (inputIds instanceof int[]) {
              for (int inputId : (int[])inputIds) {
                associateValue(mapping, value, inputId);
              }
            }
            else {
              int inputId = (int)inputIds;
              associateValue(mapping, value, inputId);
            }
          }
          else {
            int idsCount = -idCountOrSingleValue;
            ChangeBufferingList changeBufferingList = ensureFileSetCapacityForValue(value, idsCount);
            int prev = 0;

            for (int i = 0; i < idsCount; i++) {
              final int id = DataInputOutputUtil.readINT(stream);
              @NotNull Object inputIds = remapping.remap(prev + id);

              if (inputIds instanceof int[]) {
                for (int inputId : (int[])inputIds) {
                  associateValueOptimizely(mapping, value, changeBufferingList, inputId);
                }
              }
              else {
                int inputId = (int)inputIds;
                associateValueOptimizely(mapping, value, changeBufferingList, inputId);
              }

              prev += id;
            }
          }
        }
      }
    }
  }
public void readFrom(@NotNull DataInputStream stream,
                       @NotNull DataExternalizer<? extends Value> externalizer,
                       @NotNull ValueContainerInputRemapping remapping)