1#[cfg(feature = "python-bindings")]
4use pyo3::prelude::*;
5use rez_next_common::RezCoreError;
6use rez_next_package::{Package, PackageRequirement};
7use rez_next_version::Version;
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct ResolutionResult {
14 pub packages: Vec<Package>,
16 pub conflicts_resolved: bool,
18 pub resolution_time_ms: u64,
20 pub metadata: HashMap<String, String>,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct SolverConfig {
27 pub max_attempts: usize,
29 pub max_time_seconds: u64,
31 pub enable_parallel: bool,
33 pub max_workers: usize,
35 pub enable_caching: bool,
37 pub cache_ttl_seconds: u64,
39 pub prefer_latest: bool,
41 pub allow_prerelease: bool,
43 pub conflict_strategy: ConflictStrategy,
45}
46
47impl Default for SolverConfig {
48 fn default() -> Self {
49 Self {
50 max_attempts: 1000,
51 max_time_seconds: 300, enable_parallel: true,
53 max_workers: 4,
54 enable_caching: true,
55 cache_ttl_seconds: 3600, prefer_latest: true,
57 allow_prerelease: false,
58 conflict_strategy: ConflictStrategy::LatestWins,
59 }
60 }
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
65pub enum ConflictStrategy {
66 LatestWins,
68 EarliestWins,
70 FailOnConflict,
72 FindCompatible,
74}
75
76#[derive(Debug, Clone)]
78pub struct SolverRequest {
79 pub requirements: Vec<PackageRequirement>,
81 pub constraints: Vec<PackageRequirement>,
83 pub excludes: Vec<String>,
85 pub platform: Option<String>,
87 pub arch: Option<String>,
89 pub metadata: HashMap<String, String>,
91}
92
93impl SolverRequest {
94 pub fn new(requirements: Vec<PackageRequirement>) -> Self {
96 Self {
97 requirements,
98 constraints: Vec::new(),
99 excludes: Vec::new(),
100 platform: None,
101 arch: None,
102 metadata: HashMap::new(),
103 }
104 }
105
106 pub fn with_constraint(mut self, constraint: PackageRequirement) -> Self {
108 self.constraints.push(constraint);
109 self
110 }
111
112 pub fn with_exclude(mut self, package_name: String) -> Self {
114 self.excludes.push(package_name);
115 self
116 }
117
118 pub fn with_platform(mut self, platform: String) -> Self {
120 self.platform = Some(platform);
121 self
122 }
123
124 pub fn with_arch(mut self, arch: String) -> Self {
126 self.arch = Some(arch);
127 self
128 }
129}
130
131#[cfg_attr(feature = "python-bindings", pyclass)]
133#[derive(Debug)]
134pub struct DependencySolver {
135 config: SolverConfig,
137 stats: SolverStats,
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
143pub struct SolverStats {
144 pub total_resolutions: u64,
146 pub successful_resolutions: u64,
148 pub failed_resolutions: u64,
150 pub cache_hits: u64,
152 pub cache_misses: u64,
154 pub avg_resolution_time_ms: f64,
156 pub total_resolution_time_ms: u64,
158}
159
160impl Default for SolverStats {
161 fn default() -> Self {
162 Self {
163 total_resolutions: 0,
164 successful_resolutions: 0,
165 failed_resolutions: 0,
166 cache_hits: 0,
167 cache_misses: 0,
168 avg_resolution_time_ms: 0.0,
169 total_resolution_time_ms: 0,
170 }
171 }
172}
173
174#[cfg(feature = "python-bindings")]
176#[pymethods]
177impl DependencySolver {
178 #[new]
179 pub fn new_py() -> Self {
180 let config = SolverConfig::default();
181 Self {
182 config,
183 stats: SolverStats::default(),
184 }
185 }
186
187 #[getter]
189 pub fn stats(&self) -> String {
190 serde_json::to_string(&self.stats).unwrap_or_else(|_| "{}".to_string())
191 }
192}
193
194impl DependencySolver {
195 pub fn new() -> Self {
197 let config = SolverConfig::default();
198 Self {
199 config,
200 stats: SolverStats::default(),
201 }
202 }
203
204 pub fn with_config(config: SolverConfig) -> Self {
206 Self {
207 config,
208 stats: SolverStats::default(),
209 }
210 }
211
212 pub fn resolve(&self, _request: SolverRequest) -> Result<ResolutionResult, RezCoreError> {
214 Ok(ResolutionResult {
216 packages: Vec::new(),
217 conflicts_resolved: false,
218 resolution_time_ms: 0,
219 metadata: HashMap::new(),
220 })
221 }
222}
223
224impl Default for DependencySolver {
225 fn default() -> Self {
226 Self::new()
227 }
228}