jenkins_sdk/types/
common.rs

1//! Data structures returned by Jenkins APIs.
2
3use serde::{Deserialize, Serialize};
4
5/// A Jenkins job name.
6#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
7#[serde(transparent)]
8pub struct JobName(String);
9
10impl JobName {
11    #[must_use]
12    pub fn new(value: impl Into<String>) -> Self {
13        Self(value.into())
14    }
15
16    #[must_use]
17    pub fn as_str(&self) -> &str {
18        &self.0
19    }
20}
21
22impl From<&str> for JobName {
23    fn from(value: &str) -> Self {
24        Self::new(value)
25    }
26}
27
28impl From<String> for JobName {
29    fn from(value: String) -> Self {
30        Self::new(value)
31    }
32}
33
34/// A Jenkins job path (supports nested items like `folder/job`).
35///
36/// The SDK will translate a path like `a/b` into URL segments: `/job/a/job/b/...`.
37#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
38#[serde(transparent)]
39pub struct JobPath(String);
40
41impl JobPath {
42    #[must_use]
43    pub fn new(value: impl Into<String>) -> Self {
44        Self(value.into())
45    }
46
47    #[must_use]
48    pub fn as_str(&self) -> &str {
49        &self.0
50    }
51
52    pub(crate) fn url_segments(&self) -> impl Iterator<Item = &str> {
53        self.0
54            .split('/')
55            .filter(|segment| !segment.is_empty())
56            .flat_map(|segment| ["job", segment])
57    }
58}
59
60impl From<JobName> for JobPath {
61    fn from(value: JobName) -> Self {
62        Self(value.0)
63    }
64}
65
66impl From<&str> for JobPath {
67    fn from(value: &str) -> Self {
68        Self::new(value)
69    }
70}
71
72impl From<String> for JobPath {
73    fn from(value: String) -> Self {
74        Self::new(value)
75    }
76}
77
78/// A Jenkins build number (treated as a string for maximum compatibility).
79#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
80#[serde(transparent)]
81pub struct BuildNumber(String);
82
83impl BuildNumber {
84    #[must_use]
85    pub fn new(value: impl Into<String>) -> Self {
86        Self(value.into())
87    }
88
89    #[must_use]
90    pub fn as_str(&self) -> &str {
91        &self.0
92    }
93}
94
95impl From<&str> for BuildNumber {
96    fn from(value: &str) -> Self {
97        Self::new(value)
98    }
99}
100
101impl From<String> for BuildNumber {
102    fn from(value: String) -> Self {
103        Self::new(value)
104    }
105}
106
107/// A Jenkins queue item id (treated as a string for maximum compatibility).
108#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
109#[serde(transparent)]
110pub struct QueueItemId(String);
111
112impl QueueItemId {
113    #[must_use]
114    pub fn new(value: impl Into<String>) -> Self {
115        Self(value.into())
116    }
117
118    #[must_use]
119    pub fn as_str(&self) -> &str {
120        &self.0
121    }
122}
123
124impl From<&str> for QueueItemId {
125    fn from(value: &str) -> Self {
126        Self::new(value)
127    }
128}
129
130impl From<String> for QueueItemId {
131    fn from(value: String) -> Self {
132        Self::new(value)
133    }
134}
135
136/// A Jenkins view name.
137#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
138#[serde(transparent)]
139pub struct ViewName(String);
140
141impl ViewName {
142    #[must_use]
143    pub fn new(value: impl Into<String>) -> Self {
144        Self(value.into())
145    }
146
147    #[must_use]
148    pub fn as_str(&self) -> &str {
149        &self.0
150    }
151}
152
153impl From<&str> for ViewName {
154    fn from(value: &str) -> Self {
155        Self::new(value)
156    }
157}
158
159impl From<String> for ViewName {
160    fn from(value: String) -> Self {
161        Self::new(value)
162    }
163}
164
165/// A Jenkins user id.
166#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
167#[serde(transparent)]
168pub struct UserId(String);
169
170impl UserId {
171    #[must_use]
172    pub fn new(value: impl Into<String>) -> Self {
173        Self(value.into())
174    }
175
176    #[must_use]
177    pub fn as_str(&self) -> &str {
178        &self.0
179    }
180}
181
182impl From<&str> for UserId {
183    fn from(value: &str) -> Self {
184        Self::new(value)
185    }
186}
187
188impl From<String> for UserId {
189    fn from(value: String) -> Self {
190        Self::new(value)
191    }
192}
193
194/// A Jenkins computer/node name.
195#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
196#[serde(transparent)]
197pub struct ComputerName(String);
198
199impl ComputerName {
200    #[must_use]
201    pub fn new(value: impl Into<String>) -> Self {
202        Self(value.into())
203    }
204
205    #[must_use]
206    pub fn as_str(&self) -> &str {
207        &self.0
208    }
209}
210
211impl From<&str> for ComputerName {
212    fn from(value: &str) -> Self {
213        Self::new(value)
214    }
215}
216
217impl From<String> for ComputerName {
218    fn from(value: String) -> Self {
219        Self::new(value)
220    }
221}
222
223/// A Jenkins job entry in `GET /api/json`.
224#[derive(Debug, Serialize, Deserialize)]
225#[non_exhaustive]
226pub struct Job {
227    pub name: String,
228    pub url: String,
229    pub color: String,
230}
231
232/// Executor statistics from `GET /computer/api/json`.
233#[derive(Debug, Serialize, Deserialize)]
234#[serde(rename_all = "camelCase")]
235#[non_exhaustive]
236pub struct ExecutorsInfo {
237    pub total_executors: u32,
238    pub busy_executors: u32,
239    #[serde(skip)]
240    pub idle_executors: u32,
241}
242
243impl ExecutorsInfo {
244    /// Populate `idle_executors`.
245    pub fn calc_idle(mut self) -> Self {
246        self.idle_executors = self.total_executors - self.busy_executors;
247        self
248    }
249}