rez_next_version/
lib.rs

1//! # Rez Core Version
2//!
3//! Version parsing, comparison, and range handling for Rez Core.
4//!
5//! This crate provides:
6//! - Version parsing and validation
7//! - Version comparison and ordering
8//! - Version range operations
9//! - Token-based version representation
10//! - Python bindings for version operations
11
12#[cfg(feature = "python-bindings")]
13use pyo3::prelude::*;
14use rez_next_common::RezCoreError;
15
16pub mod parser;
17pub mod range; // Always available for benchmarks and core functionality
18#[cfg(feature = "python-bindings")]
19pub mod token;
20pub mod version;
21#[cfg(feature = "python-bindings")]
22pub mod version_token;
23// pub mod optimized_parser;
24
25// Re-export main types
26pub use parser::{StateMachineParser, VersionParser};
27// Always export VersionRange as it's needed by benchmarks and other core functionality
28pub use range::VersionRange;
29#[cfg(feature = "python-bindings")]
30pub use token::PyVersionToken;
31pub use version::Version;
32#[cfg(feature = "python-bindings")]
33pub use version_token::{AlphanumericVersionToken, NumericToken, VersionToken};
34// pub use optimized_parser::{OptimizedVersionParser, BatchVersionParser, ParsedVersionComponents};
35
36// Define a custom error type for version parsing
37#[derive(Debug)]
38pub struct VersionParseError(pub String);
39
40impl std::fmt::Display for VersionParseError {
41    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        write!(f, "Version parse error: {}", self.0)
43    }
44}
45
46impl std::error::Error for VersionParseError {}
47
48impl From<RezCoreError> for VersionParseError {
49    fn from(err: RezCoreError) -> Self {
50        VersionParseError(err.to_string())
51    }
52}
53
54// Make it a Python exception
55#[cfg(feature = "python-bindings")]
56pyo3::create_exception!(rez_core, PyVersionParseError, pyo3::exceptions::PyException);
57
58/// Parse a version string into a Version object
59#[cfg(feature = "python-bindings")]
60#[pyfunction]
61pub fn parse_version(version_str: &str) -> PyResult<Version> {
62    Version::parse(version_str).map_err(|e| PyErr::new::<PyVersionParseError, _>(e.to_string()))
63}
64
65/// Parse a version range string into a VersionRange object
66#[cfg(feature = "python-bindings")]
67#[pyfunction]
68pub fn parse_version_range(range_str: &str) -> PyResult<VersionRange> {
69    VersionRange::parse(range_str)
70        .map_err(|e| PyErr::new::<pyo3::exceptions::PyValueError, _>(format!("{:?}", e)))
71}
72
73/// Python module for rez_core.version
74#[cfg(feature = "python-bindings")]
75#[pymodule]
76pub fn version_module(m: &Bound<'_, PyModule>) -> PyResult<()> {
77    // Version system
78    m.add_class::<Version>()?;
79    m.add_class::<VersionRange>()?;
80    m.add_class::<PyVersionToken>()?;
81
82    // Version tokens (rez-compatible)
83    m.add_class::<VersionToken>()?;
84    m.add_class::<NumericToken>()?;
85    m.add_class::<AlphanumericVersionToken>()?;
86
87    // Version parsing functions
88    m.add_function(wrap_pyfunction!(parse_version, m)?)?;
89    m.add_function(wrap_pyfunction!(parse_version_range, m)?)?;
90
91    // Error types
92    m.add(
93        "PyVersionParseError",
94        m.py().get_type::<PyVersionParseError>(),
95    )?;
96
97    Ok(())
98}
99
100#[cfg(test)]
101mod tests;