use multi_trait::{EncodedBytes, Error, TryDecodeFrom};
fn main() {
println!("=== Multitrait Error Handling Example ===\n");
handle_empty_input();
handle_truncated_varint();
handle_invalid_encoding();
use_validated_bytes();
error_recovery();
inspect_error_source();
}
fn handle_empty_input() {
println!("1. Handling Empty Input");
println!("-----------------------");
let empty: &[u8] = &[];
match u32::try_decode_from(empty) {
Ok((value, _)) => {
println!("Unexpectedly decoded: {value}");
}
Err(e) => {
println!("✓ Correctly caught error: {e}");
println!(" Error type: UnsignedVarintDecode");
}
}
println!();
}
fn handle_truncated_varint() {
println!("2. Handling Truncated Varint");
println!("-----------------------------");
let truncated = vec![0x80];
println!("Attempting to decode truncated varint: {truncated:?}");
match u16::try_decode_from(&truncated) {
Ok((value, _)) => {
println!("Unexpectedly decoded: {value}");
}
Err(e) => {
println!("✓ Correctly caught error: {e}");
println!(" This protects against malformed data");
}
}
println!();
}
fn handle_invalid_encoding() {
println!("3. Handling Invalid Varint Encoding");
println!("------------------------------------");
let invalid = vec![0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
println!("Attempting to decode invalid varint with all continuation bits");
match u64::try_decode_from(&invalid) {
Ok((value, _)) => {
println!("Unexpectedly decoded: {value}");
}
Err(e) => {
println!("✓ Correctly caught error: {e}");
println!(" This protects against overflow attacks");
}
}
println!();
}
fn use_validated_bytes() {
println!("4. Using EncodedBytes for Validation");
println!("-------------------------------------");
let valid_data = vec![42u8];
match EncodedBytes::try_from(valid_data.clone()) {
Ok(encoded) => {
println!("✓ Valid data accepted: {valid_data:?}");
println!(" EncodedBytes length: {}", encoded.len());
}
Err(e) => {
println!("Unexpectedly rejected: {e}");
}
}
let empty_data: Vec<u8> = vec![];
match EncodedBytes::try_from(empty_data) {
Ok(_) => {
println!("Unexpectedly accepted empty data");
}
Err(e) => {
println!("✓ Empty data rejected: {e}");
}
}
let truncated_data = vec![0x80];
match EncodedBytes::try_from(truncated_data.clone()) {
Ok(_) => {
println!("Unexpectedly accepted truncated data");
}
Err(e) => {
println!("✓ Truncated data rejected: {e}");
println!(" Attempted data: {truncated_data:?}");
}
}
println!();
}
fn error_recovery() {
println!("5. Error Recovery Patterns");
println!("--------------------------");
let data = vec![0xFF, 0xFF, 0x03];
println!("Attempting to decode {data:?}...");
if let Ok((value, _)) = u8::try_decode_from(&data) {
println!("Decoded as u8: {value}");
} else {
println!("Failed to decode as u8, trying u16...");
match u16::try_decode_from(&data) {
Ok((value, _)) => {
println!("✓ Successfully decoded as u16: {value}");
}
Err(e) => {
println!("Failed to decode as u16: {e}");
}
}
}
println!();
}
fn inspect_error_source() {
println!("6. Error Source Inspection");
println!("--------------------------");
let invalid = vec![0x80, 0x80, 0x80];
match u32::try_decode_from(&invalid) {
Ok((value, _)) => {
println!("Unexpectedly decoded: {value}");
}
Err(e) => {
println!("Error occurred: {e}");
match &e {
Error::UnsignedVarintDecode { source } => {
println!(" Error type: UnsignedVarintDecode");
println!(" Source error: {source}");
println!(" This error comes from the unsigned-varint crate");
}
_ => {
println!(" Unknown error variant");
}
}
if let Some(source) = std::error::Error::source(&e) {
println!(" Error source chain: {source}");
}
}
}
println!();
}
#[allow(dead_code)]
mod application_errors {
use multi_trait::Error as MultitraitError;
#[derive(Debug)]
pub enum AppError {
InvalidData(MultitraitError),
Other(String),
}
impl std::fmt::Display for AppError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidData(e) => write!(f, "Invalid data: {e}"),
Self::Other(s) => write!(f, "{s}"),
}
}
}
impl std::error::Error for AppError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::InvalidData(e) => Some(e),
Self::Other(_) => None,
}
}
}
impl From<MultitraitError> for AppError {
fn from(e: MultitraitError) -> Self {
Self::InvalidData(e)
}
}
}