Skip to main content

arch_toolkit/types/
package.rs

1//! Package-related data types for AUR operations.
2
3use serde::{Deserialize, Serialize};
4
5/// Basic AUR package information from search results.
6///
7/// This is a lightweight representation suitable for lists and search results.
8/// For full package details, see [`AurPackageDetails`].
9#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
10pub struct AurPackage {
11    /// Canonical package name.
12    pub name: String,
13    /// Version string as reported by AUR.
14    pub version: String,
15    /// One-line description suitable for list display.
16    pub description: String,
17    /// AUR popularity score when available.
18    #[serde(default, skip_serializing_if = "Option::is_none")]
19    pub popularity: Option<f64>,
20    /// Timestamp when package was flagged out-of-date (Unix timestamp in seconds).
21    #[serde(default, skip_serializing_if = "Option::is_none")]
22    pub out_of_date: Option<u64>,
23    /// Whether package is orphaned (no active maintainer).
24    #[serde(default)]
25    pub orphaned: bool,
26    /// Package maintainer username (None if orphaned).
27    #[serde(default, skip_serializing_if = "Option::is_none")]
28    pub maintainer: Option<String>,
29}
30
31/// Full AUR package details from the info endpoint.
32///
33/// Contains comprehensive information about a package, including all dependencies,
34/// metadata, and AUR-specific fields.
35#[derive(Clone, Debug, Default, Serialize, Deserialize)]
36pub struct AurPackageDetails {
37    /// Package name.
38    pub name: String,
39    /// Full version string.
40    pub version: String,
41    /// Long description.
42    pub description: String,
43    /// Upstream project URL (may be empty if unknown).
44    pub url: String,
45    /// SPDX or human-readable license identifiers.
46    pub licenses: Vec<String>,
47    /// Group memberships.
48    pub groups: Vec<String>,
49    /// Virtual provisions supplied by this package.
50    pub provides: Vec<String>,
51    /// Required dependencies.
52    pub depends: Vec<String>,
53    /// Build dependencies.
54    pub make_depends: Vec<String>,
55    /// Optional dependencies with annotations.
56    pub opt_depends: Vec<String>,
57    /// Conflicting packages.
58    pub conflicts: Vec<String>,
59    /// Packages that this package replaces.
60    pub replaces: Vec<String>,
61    /// Package maintainer username (None if orphaned).
62    #[serde(default, skip_serializing_if = "Option::is_none")]
63    pub maintainer: Option<String>,
64    /// First submission timestamp (Unix timestamp in seconds).
65    #[serde(default, skip_serializing_if = "Option::is_none")]
66    pub first_submitted: Option<i64>,
67    /// Last modification timestamp (Unix timestamp in seconds).
68    #[serde(default, skip_serializing_if = "Option::is_none")]
69    pub last_modified: Option<i64>,
70    /// AUR popularity score when available.
71    #[serde(default, skip_serializing_if = "Option::is_none")]
72    pub popularity: Option<f64>,
73    /// Number of votes on AUR.
74    #[serde(default, skip_serializing_if = "Option::is_none")]
75    pub num_votes: Option<u64>,
76    /// Timestamp when package was flagged out-of-date (Unix timestamp in seconds).
77    #[serde(default, skip_serializing_if = "Option::is_none")]
78    pub out_of_date: Option<u64>,
79    /// Whether package is orphaned (no active maintainer).
80    #[serde(default)]
81    pub orphaned: bool,
82}
83
84/// What: Bound one official-package metadata response and candidate scan.
85///
86/// Inputs:
87/// - Constructed by callers before fetching a package detail response.
88///
89/// Output:
90/// - Maximum bytes read and result candidates considered for one request.
91///
92/// Details:
93/// - The response bound is enforced before JSON parsing.
94/// - The candidate bound prevents a broad endpoint response from expanding a
95///   single-package detail lookup into unbounded parsing work.
96#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
97pub struct MetadataFetchLimits {
98    /// Maximum response-body bytes accepted before JSON parsing.
99    pub max_response_bytes: usize,
100    /// Maximum API result rows considered while selecting an exact package.
101    pub max_candidates: usize,
102}
103
104impl Default for MetadataFetchLimits {
105    /// What: Provide conservative bounds for an official package detail request.
106    ///
107    /// Inputs: None.
108    ///
109    /// Output:
110    /// - A 512 KiB response bound and 16 candidate rows.
111    ///
112    /// Details:
113    /// - Callers can choose tighter or explicitly reviewed larger limits.
114    fn default() -> Self {
115        Self {
116            max_response_bytes: 512 * 1024,
117            max_candidates: 16,
118        }
119    }
120}
121
122/// What: Bound sequential mirror health probes made by one caller.
123///
124/// Inputs:
125/// - Constructed by callers before checking mirror probe URLs.
126///
127/// Output:
128/// - Maximum mirror rows probed in input order.
129///
130/// Details:
131/// - Transport timeout, proxy, TLS, redirect, and retry policy remain owned by
132///   the caller-provided reqwest client.
133#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
134pub struct MirrorHealthLimits {
135    /// Maximum input mirror rows probed sequentially.
136    pub max_mirrors: usize,
137}
138
139impl Default for MirrorHealthLimits {
140    /// What: Provide a conservative default mirror-health probe bound.
141    ///
142    /// Inputs: None.
143    ///
144    /// Output:
145    /// - A maximum of 16 sequential probes.
146    ///
147    /// Details:
148    /// - Sequential checks avoid an implicit concurrent request burst.
149    fn default() -> Self {
150        Self { max_mirrors: 16 }
151    }
152}
153
154/// What: Represent the reachability classification of one mirror probe.
155///
156/// Inputs:
157/// - Produced from a single caller-selected HTTP(S) probe response or error.
158///
159/// Output:
160/// - A stable status without a latency ranking or aggregate score.
161///
162/// Details:
163/// - A success status means the final response status was 2xx under the
164///   caller's reqwest redirect policy; it is not a broad performance claim.
165#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
166pub enum MirrorHealthStatus {
167    /// The probe completed with a successful 2xx HTTP status.
168    Reachable,
169    /// The probe returned a non-success status or transport error.
170    Unreachable,
171    /// The source mirror URL or caller probe path was invalid for this request.
172    Invalid,
173}
174
175/// What: Record bounded evidence from one mirror health probe.
176///
177/// Inputs:
178/// - Produced for each selected `MirrorInfo` row in input order.
179///
180/// Output:
181/// - Mirror URL, stable classification, optional final status code, and an
182///   actionable error detail when no successful response was received.
183///
184/// Details:
185/// - This is deliberately not a performance ranking and never changes mirror
186///   configuration or executes a system command.
187#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
188pub struct MirrorHealth {
189    /// Source mirror URL that was selected for the probe.
190    pub mirror_url: String,
191    /// Stable reachability classification for this one probe.
192    pub status: MirrorHealthStatus,
193    /// Final HTTP status code when a response was received.
194    pub status_code: Option<u16>,
195    /// Bounded transport or validation detail when the probe was not reachable.
196    pub detail: Option<String>,
197}
198
199/// AUR comment from a package page.
200///
201/// Contains author, date, and content of a comment, with optional timestamp
202/// for reliable chronological sorting.
203#[derive(Clone, Debug, Serialize, Deserialize)]
204pub struct AurComment {
205    /// Stable comment identifier parsed from DOM when available.
206    #[serde(default, skip_serializing_if = "Option::is_none")]
207    pub id: Option<String>,
208    /// Comment author username.
209    pub author: String,
210    /// Human-readable date string.
211    pub date: String,
212    /// Unix timestamp for sorting (None if parsing failed).
213    #[serde(default, skip_serializing_if = "Option::is_none")]
214    pub date_timestamp: Option<i64>,
215    /// URL from the date link (None if not available).
216    #[serde(default, skip_serializing_if = "Option::is_none")]
217    pub date_url: Option<String>,
218    /// Comment content text (formatted as markdown-like syntax).
219    pub content: String,
220    /// Whether this comment is pinned (shown at the top).
221    #[serde(default)]
222    pub pinned: bool,
223}