code: private CompletableFuture<Void> copyCandidates(DirectSegmentAccess segment, CompactionArgs args, TimeoutTimer timer) {
          // Collect all the candidates for copying and calculate the total serialization length.
          val toWrite = new ArrayList<TableEntry>();
          int totalLength = 0;
          for (val list : args.candidates.values()) {
              for (val c : list.getAll()) {
                  toWrite.add(c.entry);
                  totalLength += this.connector.getSerializer().getUpdateLength(c.entry);
              }
          }
  
          // Generate the necessary AttributeUpdates that will need to be applied regardless of whether we copy anything or not.
          val attributes = generateAttributeUpdates(args);
          CompletableFuture<?> result;
          if (totalLength == 0) {
              // Nothing to do; update the necessary segment attributes.
              assert toWrite.size() == 0;
              result = segment.updateAttributes(attributes, timer.getRemaining());
          } else {
              // Perform a Segment Append with re-serialized entries (Explicit versions), and atomically update the necessary
              // segment attributes.
              toWrite.sort(Comparator.comparingLong(c -> c.getKey().getVersion()));
              byte[] appendData = new byte[totalLength];
              this.connector.getSerializer().serializeUpdateWithExplicitVersion(toWrite, appendData);
              result = segment.append(appendData, attributes, timer.getRemaining());
              log.debug("TableCompactor[{}]: Compacting {}, CopyCount={}, CopyLength={}.", segment.getSegmentId(), args, toWrite, totalLength);
          }
  
          return Futures.toVoid(result);
      }
docs: Copies the {@link Candidate}s in the given {@link CompactionArgs} set to a contiguous block at the end of the Segment.
  
  @param segment A {@link DirectSegmentAccess} representing the Segment to operate on.
  @param args    A {@link CompactionArgs} containing the {@link Candidate}s to copy.
  @param timer   Timer for the operation.
  @return A CompletableFuture that, when completed, indicate the candidates have been copied.