use std::hint::black_box; use std::time::Instant; #[derive(Debug)] enum ReferenceFailure { Fault(Fault), Failed(String, Fault), } fn state_reference(value: &STATE_TYPE) -> Result { Ok(match value { STATE_TYPE::Variant0 => 0, STATE_TYPE::Variant1(number) => *number, STATE_TYPE::Variant2(text) => text.chars().count() as i64, }) } fn nullable_reference(value: &Option) -> Result { Ok(match value { None => -1, Some(text) if text == "zero" => 0, Some(text) => text.chars().count() as i64, }) } fn operation_reference(value: i64) -> Result { if value >= 0 { Ok(value) } else { Err(ReferenceFailure::Failed( "negative".into(), &FaultInfo { message: "Result.Failed", source: "reference.dever", line: 1, column: 1, }, )) } } fn propagate_reference(value: i64) -> Result { Ok(operation_reference(value)?) } fn capture_reference(value: i64) -> Result { match propagate_reference(value) { Ok(number) => Ok(RESULT_TYPE::Variant0(number)), Err(ReferenceFailure::Failed(message, _origin)) => Ok(RESULT_TYPE::Variant1(message)), Err(ReferenceFailure::Fault(fault)) => Err(fault), } } fn change_reference(value: &STATE_TYPE) -> Result { Ok(match value { STATE_TYPE::Variant2(text) => { let mut result = String::with_capacity(text.len() + "新".len()); result.push_str(text); result.push_str("新"); STATE_TYPE::Variant2(result) } _ => value.clone(), }) } fn score(value: RESULT_TYPE) -> usize { match value { RESULT_TYPE::Variant0(number) => number as usize, RESULT_TYPE::Variant1(message) => message.len(), } } fn sample( name: &str, sample: usize, implementation: &str, count: usize, mut operation: impl FnMut(usize) -> usize, ) { let start = Instant::now(); let mut checksum = 0usize; for position in 0..count { checksum = checksum.wrapping_add(black_box(operation(black_box(position)))); } println!( "{name},{sample},{implementation},{},{checksum}", start.elapsed().as_nanos() ); } fn main() { let states = [ STATE_TYPE::Variant0, STATE_TYPE::Variant1(42), STATE_TYPE::Variant2("雪山树林".repeat(16)), ]; let texts = [None, Some("zero".into()), Some("雪山树林".repeat(16))]; for state in &states { assert_eq!( GENERATED_STATE(state).unwrap(), state_reference(state).unwrap() ); assert_eq!( GENERATED_CHANGE(state).unwrap(), change_reference(state).unwrap() ); } for text in &texts { assert_eq!( GENERATED_NULLABLE(text).unwrap(), nullable_reference(text).unwrap() ); } for value in [i64::MIN, -1, 0, 1, i64::MAX] { assert_eq!( GENERATED_PROPAGATE(value).map_err(|_| ()), propagate_reference(value).map_err(|_| ()) ); assert_eq!( GENERATED_CAPTURE(value).unwrap(), capture_reference(value).unwrap() ); } println!("case,sample,implementation,elapsed_ns,checksum"); for iteration in 0..9 { for generated in if iteration % 2 == 0 { [true, false] } else { [false, true] } { let implementation = if generated { "dever" } else { "rust" }; if generated { sample( "choice_payload", iteration, implementation, 1_000_000, |position| GENERATED_STATE(black_box(&states[position % 3])).unwrap() as usize, ); sample( "nullable_text", iteration, implementation, 1_000_000, |position| { GENERATED_NULLABLE(black_box(&texts[position % 3])).unwrap() as usize }, ); sample( "default_failure", iteration, implementation, 500_000, |position| { black_box(GENERATED_PROPAGATE((position % 8) as i64 - 1)).unwrap_or(7) as usize }, ); sample( "capture_failure", iteration, implementation, 500_000, |position| { score(black_box( GENERATED_CAPTURE((position % 8) as i64 - 1).unwrap(), )) }, ); sample( "choice_copy", iteration, implementation, 300_000, |_| match black_box(GENERATED_CHANGE(black_box(&states[2])).unwrap()) { STATE_TYPE::Variant2(text) => text.len(), _ => unreachable!(), }, ); } else { sample( "choice_payload", iteration, implementation, 1_000_000, |position| state_reference(black_box(&states[position % 3])).unwrap() as usize, ); sample( "nullable_text", iteration, implementation, 1_000_000, |position| { nullable_reference(black_box(&texts[position % 3])).unwrap() as usize }, ); sample( "default_failure", iteration, implementation, 500_000, |position| { black_box(propagate_reference((position % 8) as i64 - 1)).unwrap_or(7) as usize }, ); sample( "capture_failure", iteration, implementation, 500_000, |position| { score(black_box( capture_reference((position % 8) as i64 - 1).unwrap(), )) }, ); sample( "choice_copy", iteration, implementation, 300_000, |_| match black_box(change_reference(black_box(&states[2])).unwrap()) { STATE_TYPE::Variant2(text) => text.len(), _ => unreachable!(), }, ); } } } }