Copy uni-dimensional measurements to the MfgEvent.

def _copy_unidimensional_measurement(
      self, phase, name, measurement, mfg_event):
    """Copy uni-dimensional measurements to the MfgEvent."""
    mfg_measurement = mfg_event.measurement.add()

    # Copy basic measurement fields.
    mfg_measurement.name = name
    if measurement.docstring:
      mfg_measurement.description = measurement.docstring
    mfg_measurement.parameter_tag.append(phase.name)
    if (measurement.units and
        measurement.units.code in test_runs_converter.UOM_CODE_MAP):
      mfg_measurement.unit_code = (
          test_runs_converter.UOM_CODE_MAP[measurement.units.code])

    # Copy failed measurements as failure_codes. This happens early to include
    # unset measurements.
    if (measurement.outcome != measurements.Outcome.PASS and
        phase.outcome != htf_test_record.PhaseOutcome.SKIP):
      failure_code = mfg_event.failure_codes.add()
      failure_code.code = name
      failure_code.details = '\n'.join(str(v) for v in measurement.validators)

    # Copy measurement value.
    measured_value = measurement.measured_value
    status_str = MEASUREMENT_OUTCOME_TO_TEST_RUN_STATUS_NAME[
        measurement.outcome]
    mfg_measurement.status = test_runs_pb2.Status.Value(status_str)
    if not measured_value.is_value_set:
      return
    value = measured_value.value

    if isinstance(value, numbers.Number):
      mfg_measurement.numeric_value = float(value)
    elif isinstance(value, bytes):
      # text_value expects unicode or ascii-compatible strings, so we must
      # 'decode' it, even if it's actually just garbage bytestring data.
      mfg_measurement.text_value = unicode(value, errors='replace')
    elif isinstance(value, unicode):
      # Don't waste time and potential errors decoding unicode.
      mfg_measurement.text_value = value
    else:
      # Coercing to string.
      mfg_measurement.text_value = str(value)

    # Copy measurement validators.
    for validator in measurement.validators:
      if isinstance(validator, validators.RangeValidatorBase):
        if validator.minimum is not None:
          mfg_measurement.numeric_minimum = float(validator.minimum)
        if validator.maximum is not None:
          mfg_measurement.numeric_maximum = float(validator.maximum)
      elif isinstance(validator, validators.RegexMatcher):
        mfg_measurement.expected_text = validator.regex
      else:
        mfg_measurement.description += '\nValidator: ' + str(validator)