Skip to content

Commit 6863dc2

Browse files
committed
damn
1 parent 5edf4d4 commit 6863dc2

File tree

6 files changed

+144
-7
lines changed

6 files changed

+144
-7
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ rust-version.workspace = true
3434

3535
[features]
3636
diagnostics = ["tabwriter", "human_bytes"]
37+
serde = ["dep:serde", "petgraph/serde-1"]
3738

3839
[dependencies]
3940
ahash = "0.8.12"

src/conflict.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use petgraph::{
1010
graph::{DiGraph, EdgeIndex, EdgeReference, NodeIndex},
1111
visit::{Bfs, DfsPostOrder, EdgeRef},
1212
};
13+
#[cfg(feature = "serde")]
14+
use serde::{Deserialize, Serialize};
1315

1416
use crate::{
1517
DependencyProvider, Interner, Requirement,
@@ -22,7 +24,8 @@ use crate::{
2224
};
2325

2426
/// Represents the cause of the solver being unable to find a solution
25-
#[derive(Debug)]
27+
#[derive(Debug, Clone)]
28+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2629
pub struct Conflict {
2730
/// The clauses involved in an unsatisfiable conflict
2831
clauses: Vec<ClauseId>,
@@ -218,6 +221,7 @@ impl Conflict {
218221

219222
/// A node in the graph representation of a [`Conflict`]
220223
#[derive(Copy, Clone, Eq, PartialEq)]
224+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
221225
pub enum ConflictNode {
222226
/// Node corresponding to a solvable
223227
Solvable(SolvableOrRootId),
@@ -247,6 +251,7 @@ impl ConflictNode {
247251

248252
/// An edge in the graph representation of a [`Conflict`]
249253
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
254+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
250255
pub enum ConflictEdge {
251256
/// The target node is a candidate for the dependency specified by the
252257
/// [`Requirement`]
@@ -273,6 +278,7 @@ impl ConflictEdge {
273278

274279
/// Conflict causes
275280
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
281+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
276282
pub enum ConflictCause {
277283
/// The solvable is locked
278284
Locked(SolvableId),
@@ -292,6 +298,7 @@ pub enum ConflictCause {
292298
/// - They all have the same name
293299
/// - They all have the same predecessor nodes
294300
/// - They all have the same successor nodes
301+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
295302
pub struct MergedConflictNode {
296303
/// The list of solvable ids that have been merged into this node.
297304
pub ids: Vec<SolvableId>,
@@ -303,6 +310,7 @@ pub struct MergedConflictNode {
303310
/// solvable's requirements are included in the graph, only those that are
304311
/// directly or indirectly involved in the conflict.
305312
#[derive(Clone)]
313+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
306314
pub struct ConflictGraph {
307315
/// The conflict graph as a directed petgraph.
308316
pub graph: DiGraph<ConflictNode, ConflictEdge>,

src/internal/id.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ use std::{
44
};
55

66
use crate::{Interner, internal::arena::ArenaId};
7+
#[cfg(feature = "serde")]
8+
use serde::{Deserialize, Serialize};
79

810
/// The id associated to a package name
911
#[repr(transparent)]
1012
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
11-
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1214
#[cfg_attr(feature = "serde", serde(transparent))]
1315
pub struct NameId(pub u32);
1416

@@ -25,7 +27,7 @@ impl ArenaId for NameId {
2527
/// The id associated with a generic string
2628
#[repr(transparent)]
2729
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Ord, PartialOrd)]
28-
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
30+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2931
#[cfg_attr(feature = "serde", serde(transparent))]
3032
pub struct StringId(pub u32);
3133

@@ -42,7 +44,7 @@ impl ArenaId for StringId {
4244
/// The id associated with a VersionSet.
4345
#[repr(transparent)]
4446
#[derive(Clone, Default, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
45-
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
47+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4648
#[cfg_attr(feature = "serde", serde(transparent))]
4749
pub struct VersionSetId(pub u32);
4850

@@ -59,7 +61,7 @@ impl ArenaId for VersionSetId {
5961
/// The id associated with a Condition.
6062
#[repr(transparent)]
6163
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
62-
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
64+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6365
#[cfg_attr(feature = "serde", serde(transparent))]
6466
pub struct ConditionId(NonZero<u32>);
6567

@@ -89,7 +91,7 @@ impl ArenaId for ConditionId {
8991
/// The id associated with a union (logical OR) of two or more version sets.
9092
#[repr(transparent)]
9193
#[derive(Clone, Default, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
92-
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
94+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9395
#[cfg_attr(feature = "serde", serde(transparent))]
9496
pub struct VersionSetUnionId(pub u32);
9597

@@ -106,7 +108,7 @@ impl ArenaId for VersionSetUnionId {
106108
/// The id associated to a solvable
107109
#[repr(transparent)]
108110
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Ord, PartialOrd)]
109-
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
111+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
110112
#[cfg_attr(feature = "serde", serde(transparent))]
111113
pub struct SolvableId(pub u32);
112114

@@ -128,6 +130,8 @@ impl From<SolvableId> for u32 {
128130

129131
#[repr(transparent)]
130132
#[derive(Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug, Hash)]
133+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
134+
#[cfg_attr(feature = "serde", serde(transparent))]
131135
pub(crate) struct ClauseId(NonZeroU32);
132136

133137
impl ClauseId {
@@ -241,6 +245,8 @@ impl<I: Interner> Display for DisplaySolvableId<'_, I> {
241245

242246
#[repr(transparent)]
243247
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
248+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
249+
#[cfg_attr(feature = "serde", serde(transparent))]
244250
pub struct SolvableOrRootId(u32);
245251

246252
impl SolvableOrRootId {

src/solver/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use elsa::FrozenMap;
1010
use encoding::Encoder;
1111
use indexmap::IndexMap;
1212
use itertools::Itertools;
13+
#[cfg(feature = "serde")]
14+
use serde::{Deserialize, Serialize};
1315
use variable_map::VariableMap;
1416
use watch_map::WatchMap;
1517

@@ -214,10 +216,12 @@ impl<D: DependencyProvider> Solver<D, NowOrNeverRuntime> {
214216

215217
/// The root cause of a solver error.
216218
#[derive(Debug)]
219+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
217220
pub enum UnsolvableOrCancelled {
218221
/// The problem was unsolvable.
219222
Unsolvable(Conflict),
220223
/// The solving process was cancelled.
224+
#[cfg_attr(feature = "serde", serde(skip))]
221225
Cancelled(Box<dyn Any>),
222226
}
223227

tests/solver/main.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,3 +1069,120 @@ fn solve_for_snapshot<D: DependencyProvider>(
10691069
Err(UnsolvableOrCancelled::Cancelled(reason)) => *reason.downcast().unwrap(),
10701070
}
10711071
}
1072+
1073+
#[cfg(feature = "serde")]
1074+
#[test]
1075+
fn test_conflict_serialization_json() {
1076+
let mut provider = BundleBoxProvider::from_packages(&[
1077+
("a", 1, vec!["b"]),
1078+
("b", 1, vec!["c 2"]),
1079+
("c", 1, vec![]),
1080+
]);
1081+
1082+
let requirements = provider.requirements(&["a"]);
1083+
let mut solver = Solver::new(provider);
1084+
let problem = Problem::new().requirements(requirements);
1085+
1086+
let Err(UnsolvableOrCancelled::Unsolvable(conflict)) = solver.solve(problem) else {
1087+
panic!("Expected an unsolvable conflict");
1088+
};
1089+
1090+
let json = serde_json::to_string(&conflict).expect("Failed to serialize conflict to JSON");
1091+
let _deserialized_conflict: resolvo::conflict::Conflict =
1092+
serde_json::from_str(&json).expect("Failed to deserialize conflict from JSON");
1093+
let graph = conflict.graph(&solver);
1094+
let _graph_json =
1095+
serde_json::to_string(&graph).expect("Failed to serialize ConflictGraph to JSON");
1096+
let unsolvable = UnsolvableOrCancelled::Unsolvable(conflict);
1097+
let _unsolvable_json =
1098+
serde_json::to_string(&unsolvable).expect("Failed to serialize UnsolvableOrCancelled");
1099+
let parsed: serde_json::Value = serde_json::from_str(&json).expect("Invalid JSON");
1100+
assert!(
1101+
parsed.get("clauses").is_some(),
1102+
"Conflict should have clauses field"
1103+
);
1104+
}
1105+
1106+
#[cfg(feature = "serde")]
1107+
#[test]
1108+
fn test_multiple_error_scenarios() {
1109+
let mut provider = BundleBoxProvider::from_packages(&[("foo", 1, vec!["nonexistent"])]);
1110+
1111+
let requirements = provider.requirements(&["foo"]);
1112+
let mut solver = Solver::new(provider);
1113+
let problem = Problem::new().requirements(requirements);
1114+
1115+
let Err(UnsolvableOrCancelled::Unsolvable(conflict)) = solver.solve(problem) else {
1116+
panic!("Expected unsolvable conflict in scenario 1");
1117+
};
1118+
1119+
let json = serde_json::to_string(&conflict).expect("Scenario 1: JSON serialization failed");
1120+
let _: resolvo::conflict::Conflict =
1121+
serde_json::from_str(&json).expect("Scenario 1: JSON deserialization failed");
1122+
1123+
let mut provider = BundleBoxProvider::from_packages(&[("x", 1, vec!["y 2"]), ("y", 1, vec![])]);
1124+
1125+
let requirements = provider.requirements(&["x"]);
1126+
let mut solver = Solver::new(provider);
1127+
let problem = Problem::new().requirements(requirements);
1128+
1129+
let Err(UnsolvableOrCancelled::Unsolvable(conflict)) = solver.solve(problem) else {
1130+
panic!("Expected unsolvable conflict in scenario 2");
1131+
};
1132+
1133+
let json = serde_json::to_string(&conflict).expect("Scenario 2: JSON serialization failed");
1134+
let _: resolvo::conflict::Conflict =
1135+
serde_json::from_str(&json).expect("Scenario 2: JSON deserialization failed");
1136+
}
1137+
1138+
#[cfg(feature = "serde")]
1139+
#[test]
1140+
fn test_serialization_formats() {
1141+
let mut provider = BundleBoxProvider::from_packages(&[("test", 1, vec!["missing"])]);
1142+
1143+
let requirements = provider.requirements(&["test"]);
1144+
let mut solver = Solver::new(provider);
1145+
let problem = Problem::new().requirements(requirements);
1146+
1147+
let Err(UnsolvableOrCancelled::Unsolvable(conflict)) = solver.solve(problem) else {
1148+
panic!("Expected unsolvable conflict");
1149+
};
1150+
1151+
let json = serde_json::to_string(&conflict).expect("JSON serialization failed");
1152+
let _: resolvo::conflict::Conflict =
1153+
serde_json::from_str(&json).expect("JSON deserialization failed");
1154+
let pretty_json =
1155+
serde_json::to_string_pretty(&conflict).expect("Pretty JSON serialization failed");
1156+
let _: resolvo::conflict::Conflict =
1157+
serde_json::from_str(&pretty_json).expect("Pretty JSON deserialization failed");
1158+
let value: serde_json::Value =
1159+
serde_json::to_value(&conflict).expect("Value conversion failed");
1160+
let _: resolvo::conflict::Conflict =
1161+
serde_json::from_value(value).expect("Value deserialization failed");
1162+
}
1163+
1164+
#[cfg(feature = "serde")]
1165+
#[test]
1166+
fn test_unsolvable_or_cancelled_enum_structure() {
1167+
let mut provider = BundleBoxProvider::from_packages(&[("test", 1, vec!["missing"])]);
1168+
1169+
let requirements = provider.requirements(&["test"]);
1170+
let mut solver = Solver::new(provider);
1171+
let problem = Problem::new().requirements(requirements);
1172+
1173+
let Err(UnsolvableOrCancelled::Unsolvable(conflict)) = solver.solve(problem) else {
1174+
panic!("Expected unsolvable conflict");
1175+
};
1176+
1177+
let unsolvable = UnsolvableOrCancelled::Unsolvable(conflict);
1178+
let json = serde_json::to_string(&unsolvable).expect("Serialization failed");
1179+
let parsed: serde_json::Value = serde_json::from_str(&json).expect("Invalid JSON");
1180+
assert!(
1181+
parsed.get("Unsolvable").is_some(),
1182+
"Should contain Unsolvable variant"
1183+
);
1184+
assert!(
1185+
parsed.get("Cancelled").is_none(),
1186+
"Should not contain Cancelled variant when serializing Unsolvable"
1187+
);
1188+
}

0 commit comments

Comments
 (0)