///|
/// Reports which stage prevented a profile conversion.
pub(all) enum ConversionError {
  ConversionParseFailed(RomanReportError)
  ConversionFormatFailed(FormatError)
} derive(Eq, Debug)

///|
/// Retains source evidence and the deterministic target representation.
pub(all) struct RomanConversionReport {
  input : String
  value : Int
  output : String
  source_report : ParseReport
  target_config : FormatConfig
} derive(Eq, Debug)

///|
/// Parse with one explicit profile and format with another.
pub fn convert_roman(
  input : String,
  source_config : ParseConfig,
  target_config : FormatConfig,
) -> Result[RomanConversionReport, ConversionError] {
  let source_report = match parse_with_config(input, source_config) {
    Ok(report) => report
    Err(error) => return Err(ConversionParseFailed(error))
  }
  let output = match format_with_config(source_report.value, target_config) {
    Ok(text) => text
    Err(error) => return Err(ConversionFormatFailed(error))
  }
  Ok({ input, value: source_report.value, output, source_report, target_config })
}