@VisibleForTesting
  <R> R readAttributeValue(int attributesRecordId,
                           int fileId,
                           int attributeId,
                           ByteBufferReader<R> reader) throws IOException {
    return storage.readRecord(attributesRecordId, buffer -> {
      AttributesRecord attributesRecord = new AttributesRecord(buffer);
      attributesRecord.checkBackrefFile(attributesRecordId, fileId);

      if (!attributesRecord.findAttributeInDirectoryRecord(attributeId)) {
        return null;
      }

      AttributeEntry attributeEntry = attributesRecord.currentEntry();
      if (attributeEntry.isValueInlined()) {
        return reader.read(attributeEntry.inlinedValueAsSlice());
      }

      int dedicatedRecordId = attributeEntry.dedicatedValueRecordId();
      return storage.readRecord(
        dedicatedRecordId,
        dedicatedRecordBuffer -> reader.read(
          readDedicatedRecordPayloadAsSlice(
            attributesRecordId, fileId, attributeEntry.attributeId,
            dedicatedRecordBuffer
          )
        )
      );
    });
  }
@VisibleForTesting
  <R> R readAttributeValue(int attributesRecordId,
                           int fileId,
                           int attributeId,
                           ByteBufferReader<R> reader)