docs: def _process_upload_descriptor(self, ud):
          # type: (Uploader, blobxfer.models.upload.Descriptor) -> None
          """Process upload descriptor
          :param Uploader self: this
          :param blobxfer.models.upload.Descriptor: upload descriptor
          """
          # get upload offsets
          offsets, resume_bytes = ud.next_offsets()
          # add resume bytes to counter
          if resume_bytes is not None:
              with self._transfer_lock:
                  self._upload_bytes_total += ud.entity.size
                  self._upload_bytes_sofar += resume_bytes
                  logger.debug('adding {} sofar {} from {}'.format(
                      resume_bytes, self._upload_bytes_sofar, ud.entity.name))
              del resume_bytes
          # check if all operations completed
          if offsets is None and ud.all_operations_completed:
              # finalize file
              self._finalize_upload(ud)
              # accounting
              with self._upload_lock:
                  if ud.entity.is_encrypted:
                      self._ud_map.pop(ud.unique_id)
                  self._upload_set.remove(ud.unique_id)
                  self._upload_sofar += 1
              return
          # if nothing to upload, re-enqueue for finalization
          if offsets is None:
              self._upload_queue.put(ud)
              return
          # prepare upload
          if offsets.chunk_num == 0:
              self._prepare_upload(ud.entity)
          # prepare replicae targets
          if blobxfer.util.is_not_empty(ud.entity.replica_targets):
              for ase in ud.entity.replica_targets:
                  if offsets.chunk_num == 0:
                      self._prepare_upload(ase)
          # encrypt if necessary
          if ud.entity.is_encrypted and ud.entity.size > 0:
              # send iv through hmac if first chunk
              if offsets.chunk_num == 0:
                  ud.hmac_data(ud.current_iv)
              # encrypt data
              if self._crypto_offload is None:
                  # read data from file and encrypt
                  data, _ = ud.read_data(offsets)
                  encdata = blobxfer.operations.crypto.aes_cbc_encrypt_data(
                      ud.entity.encryption_metadata.symmetric_key,
                      ud.current_iv, data, offsets.pad)
                  # send encrypted data through hmac
                  ud.hmac_data(encdata)
                  data = encdata
                  # save last 16 encrypted bytes for next IV
                  ud.current_iv = \
                      encdata[-blobxfer.models.crypto.AES256_BLOCKSIZE_BYTES:]
              else:  # noqa
                  # crypto offload is not supported with AES256-CBC FullBlob
                  raise NotImplementedError()
                  # self._crypto_offload.add_encrypt_chunk(
                  #     str(ud.local_path.absolute_path), offsets,
                  #     ud.entity.encryption_metadata.symmetric_key,
                  #     ud.current_iv)
                  # encrypted data will be retrieved from a temp file once
                  # retrieved from crypto queue
                  # return_early = True
          else:
              data, newoffset = ud.read_data(offsets)
              # set new offset if stdin
              if newoffset is not None:
                  offsets = newoffset
          # re-enqueue for other threads to upload if not append
          if ud.entity.mode != blobxfer.models.azure.StorageModes.Append:
              self._upload_queue.put(ud)
          # no data can be returned on stdin uploads
          if ud.local_path.use_stdin and not data:
              return
          # add data to transfer queue
          with self._transfer_lock:
              self._transfer_set.add(
                  blobxfer.operations.upload.Uploader.create_unique_transfer_id(
                      ud.local_path, ud.entity, offsets))
          self._transfer_queue.put((ud, ud.entity, offsets, data))
          # iterate replicas
          if blobxfer.util.is_not_empty(ud.entity.replica_targets):
              for ase in ud.entity.replica_targets:
                  with self._transfer_lock:
                      self._transfer_set.add(
                          blobxfer.operations.upload.Uploader.
                          create_unique_transfer_id(ud.local_path, ase, offsets)
                      )
                  self._transfer_queue.put((ud, ase, offsets, data))