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