synta-python 0.1.4

Python extension module for the synta ASN.1 library
Documentation
//! Error handling for Python bindings
//!
//! Converts Synta errors to Python exceptions.
//!
//! Because both `synta::Error` and `pyo3::PyErr` are defined in foreign crates,
//! the orphan rule prevents `impl From<synta::Error> for PyErr` directly.
//! The local newtype `SyntaErr` bridges the gap: callers use `.map_err(SyntaErr)?`
//! and pyo3's `?` machinery picks up `From<SyntaErr> for PyErr`.

use pyo3::exceptions::{PyEOFError, PyOverflowError, PyRuntimeError, PyValueError};
use pyo3::{create_exception, PyErr};

// Create a custom exception type visible from Python.
create_exception!(synta, SyntaError, pyo3::exceptions::PyException);

/// Local newtype wrapper around `synta::Error` that satisfies the orphan rule.
pub(crate) struct SyntaErr(pub synta::Error);

impl From<synta::Error> for SyntaErr {
    fn from(e: synta::Error) -> Self {
        SyntaErr(e)
    }
}

impl From<SyntaErr> for PyErr {
    fn from(SyntaErr(err): SyntaErr) -> PyErr {
        match err {
            synta::Error::UnexpectedEof { position } => {
                PyEOFError::new_err(format!("Unexpected end of input at position {}", position))
            }
            synta::Error::InvalidTag { position, byte } => PyValueError::new_err(format!(
                "Invalid ASN.1 tag at position {}: 0x{:02x}",
                position, byte
            )),
            synta::Error::InvalidLength { position } => {
                PyValueError::new_err(format!("Invalid length encoding at position {}", position))
            }
            synta::Error::LengthOverflow => PyOverflowError::new_err("Length value overflow"),
            synta::Error::LengthExceedsMaximum {
                position,
                length,
                max_length,
            } => PyValueError::new_err(format!(
                "Length {} exceeds maximum {} at position {}",
                length, max_length, position
            )),
            synta::Error::MaxDepthExceeded {
                position,
                max_depth,
            } => PyValueError::new_err(format!(
                "Maximum nesting depth {} exceeded at position {}",
                max_depth, position
            )),
            synta::Error::UnexpectedTag {
                position,
                expected,
                actual,
            } => PyValueError::new_err(format!(
                "Unexpected tag at position {}: expected {:?}, got {:?}",
                position, expected, actual
            )),
            synta::Error::InvalidEncoding {
                position,
                tag,
                reason,
            } => PyValueError::new_err(format!(
                "Invalid encoding for {:?} at position {}: {}",
                tag, position, reason
            )),
            synta::Error::IntegerOverflow { position } => {
                PyOverflowError::new_err(format!("Integer overflow at position {}", position))
            }
            synta::Error::InvalidOid { position } => {
                PyValueError::new_err(format!("Invalid OID encoding at position {}", position))
            }
            synta::Error::InvalidString {
                position,
                string_type,
                reason,
            } => PyValueError::new_err(format!(
                "Invalid {} at position {}: {}",
                string_type, position, reason
            )),
            synta::Error::InvalidTime { position } => {
                PyValueError::new_err(format!("Invalid time format at position {}", position))
            }
            synta::Error::DerViolation { position, reason } => PyValueError::new_err(format!(
                "DER violation at position {}: {}",
                position, reason
            )),
            synta::Error::IndefiniteLengthInDer { position } => PyValueError::new_err(format!(
                "Indefinite length not allowed in DER at position {}",
                position
            )),
            synta::Error::CerViolation { position, reason } => PyValueError::new_err(format!(
                "CER violation at position {}: {}",
                position, reason
            )),
            synta::Error::UnfinishedConstructed => {
                PyRuntimeError::new_err("Constructed encoder not properly finished")
            }
            synta::Error::NoConstructedToFinish => {
                PyRuntimeError::new_err("No constructed element to finish")
            }
            synta::Error::LengthTooLarge => PyValueError::new_err("Length too large to encode"),
            synta::Error::Custom(msg) => PyRuntimeError::new_err(msg),
        }
    }
}