1use crate::constraint::Constraint;
6use crate::package::Link;
7use std::collections::HashMap;
8
9#[derive(Debug, Clone)]
11pub enum Reason {
12 RootRequire {
14 package_name: String,
15 constraint: Constraint,
16 },
17 Fixed { package: usize },
19 PackageConflict(Link),
21 PackageRequires(Link),
23 PackageSameName(String),
25 Learned(usize),
27 PackageAlias { alias: usize },
29 PackageInverseAlias { package: usize },
31 LockedFilterListRemoved { package: usize },
33}
34
35impl Reason {
36 pub fn code(&self) -> u8 {
37 match self {
38 Reason::RootRequire { .. } => 2,
39 Reason::Fixed { .. } => 3,
40 Reason::PackageConflict(_) => 6,
41 Reason::PackageRequires(_) => 7,
42 Reason::PackageSameName(_) => 10,
43 Reason::Learned(_) => 12,
44 Reason::PackageAlias { .. } => 13,
45 Reason::PackageInverseAlias { .. } => 14,
46 Reason::LockedFilterListRemoved { .. } => 15,
47 }
48 }
49}
50
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
54pub enum RuleKind {
55 Generic,
56 TwoLiterals,
57 MultiConflict,
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
62pub enum RuleType {
63 Package = 0,
64 Request = 1,
65 Learned = 4,
66}
67
68#[derive(Debug, Clone)]
69pub struct Rule {
70 pub kind: RuleKind,
71 pub literals: Vec<i64>,
74 pub reason: Reason,
75 pub rule_type: Option<RuleType>,
78 pub disabled: bool,
79}
80
81impl Rule {
82 pub fn generic(mut literals: Vec<i64>, reason: Reason) -> Rule {
84 literals.sort_unstable();
85 Rule {
86 kind: RuleKind::Generic,
87 literals,
88 reason,
89 rule_type: None,
90 disabled: false,
91 }
92 }
93
94 pub fn two_literals(l1: i64, l2: i64, reason: Reason) -> Rule {
96 Rule {
97 kind: RuleKind::TwoLiterals,
98 literals: if l1 < l2 { vec![l1, l2] } else { vec![l2, l1] },
99 reason,
100 rule_type: None,
101 disabled: false,
102 }
103 }
104
105 pub fn multi_conflict(mut literals: Vec<i64>, reason: Reason) -> Rule {
107 literals.sort_unstable();
108 Rule {
109 kind: RuleKind::MultiConflict,
110 literals,
111 reason,
112 rule_type: None,
113 disabled: false,
114 }
115 }
116
117 pub fn is_assertion(&self) -> bool {
118 self.kind == RuleKind::Generic && self.literals.len() == 1
119 }
120
121 pub fn is_enabled(&self) -> bool {
122 !self.disabled
123 }
124
125 pub fn required_package<'a>(&'a self, arena: &'a [crate::package::Package]) -> Option<&'a str> {
127 match &self.reason {
128 Reason::RootRequire { package_name, .. } => Some(package_name),
129 Reason::Fixed { package } | Reason::LockedFilterListRemoved { package } => {
130 Some(&arena[*package].name)
131 }
132 Reason::PackageRequires(link) => Some(&link.target),
133 _ => None,
134 }
135 }
136}
137
138#[derive(Debug, Clone, PartialEq, Eq, Hash)]
143struct RuleKey {
144 kind: RuleKind,
145 literals: Vec<i64>,
146}
147
148#[derive(Debug, Default)]
152pub struct RuleSet {
153 pub rules: Vec<Rule>,
154 pub rule_by_id: Vec<usize>,
156 by_type: [Vec<usize>; 3],
158 keys: HashMap<RuleKey, usize>,
159}
160
161impl RuleSet {
162 pub fn new() -> RuleSet {
163 RuleSet::default()
164 }
165
166 fn slot(rule_type: RuleType) -> usize {
167 match rule_type {
168 RuleType::Package => 0,
169 RuleType::Request => 1,
170 RuleType::Learned => 2,
171 }
172 }
173
174 pub fn add(&mut self, mut rule: Rule, rule_type: RuleType) -> (usize, bool) {
178 let key = RuleKey {
179 kind: rule.kind,
180 literals: rule.literals.clone(),
181 };
182 let id = self.rules.len();
183 if self.keys.contains_key(&key) {
184 self.rules.push(rule);
185 return (id, false);
186 }
187 rule.rule_type = Some(rule_type);
188 self.rules.push(rule);
189 self.rule_by_id.push(id);
190 self.by_type[Self::slot(rule_type)].push(id);
191 self.keys.insert(key, id);
192 (id, true)
193 }
194
195 pub fn len(&self) -> usize {
197 self.rule_by_id.len()
198 }
199
200 pub fn is_empty(&self) -> bool {
201 self.rule_by_id.is_empty()
202 }
203
204 pub fn ids_of_type(&self, rule_type: RuleType) -> &[usize] {
206 &self.by_type[Self::slot(rule_type)]
207 }
208
209 pub fn ids_in_iterator_order(&self) -> Vec<usize> {
211 let mut out = Vec::with_capacity(self.rules.len());
212 for slot in &self.by_type {
213 out.extend(slot.iter().copied());
214 }
215 out
216 }
217}