Skip to main content

rust_toolchain/
toolchain.rs

1use crate::{Channel, ComponentSet, Date, Target, TargetSet};
2
3/// A Rust toolchain
4///
5/// # Reading materials
6///
7/// - [`rustup concepts: toolchains`]
8///
9/// [`rustup concepts: toolchains`]: https://rust-lang.github.io/rustup/concepts/toolchains.html
10#[derive(Clone, Debug, PartialEq, Eq)]
11#[non_exhaustive]
12pub struct Toolchain {
13    channel: Channel,
14    date: Option<Date>,
15    host: Target,
16
17    components: ComponentSet,
18    targets: TargetSet,
19}
20
21impl Toolchain {
22    /// Create a new toolchain instance
23    pub fn new(
24        channel: Channel,
25        date: Option<Date>,
26        host: Target,
27        components: ComponentSet,
28        targets: TargetSet,
29    ) -> Self {
30        Self {
31            channel,
32            date,
33            host,
34            components,
35            targets,
36        }
37    }
38
39    /// The release associated with the toolchain
40    pub fn channel(&self) -> &Channel {
41        &self.channel
42    }
43
44    /// The date on which the toolchain was released
45    pub fn date(&self) -> Option<&Date> {
46        self.date.as_ref()
47    }
48
49    /// The host target associated with the toolchain
50    pub fn host(&self) -> &Target {
51        &self.host
52    }
53
54    /// The components associated with the toolchain
55    pub fn components(&self) -> &ComponentSet {
56        &self.components
57    }
58
59    /// The targets associated with the toolchain
60    pub fn targets(&self) -> &TargetSet {
61        &self.targets
62    }
63
64    /// Update the associated channel
65    pub fn set_channel(&mut self, channel: Channel) {
66        self.channel = channel;
67    }
68
69    /// Update the associated toolchain release date
70    pub fn set_date(&mut self, date: Option<Date>) {
71        self.date = date;
72    }
73
74    /// Updated the associated host platform
75    pub fn set_host(&mut self, host: Target) {
76        self.host = host;
77    }
78
79    /// Update the associated toolchain components
80    pub fn set_components(&mut self, components: ComponentSet) {
81        self.components = components;
82    }
83
84    /// Update the associated toolchain targets
85    pub fn set_targets(&mut self, targets: TargetSet) {
86        self.targets = targets;
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93    use crate::{Component, RustVersion};
94    use std::ptr;
95
96    #[test]
97    fn create_toolchain() {
98        let channel = Channel::stable(RustVersion::new(1, 2, 3));
99
100        let toolchain = Toolchain::new(
101            channel,
102            None,
103            Target::host(),
104            ComponentSet::default(),
105            TargetSet::default(),
106        );
107
108        assert!(toolchain.channel().is_stable());
109        assert_eq!(toolchain.host(), &Target::host());
110    }
111
112    #[test]
113    fn channel() {
114        let channel = Channel::stable(RustVersion::new(1, 2, 3));
115        let mut toolchain = Toolchain::new(
116            channel,
117            None,
118            Target::host(),
119            ComponentSet::default(),
120            TargetSet::default(),
121        );
122
123        assert!(toolchain.channel().is_stable());
124
125        toolchain.set_channel(Channel::beta(RustVersion::new(1, 2, 4)));
126
127        assert!(toolchain.channel().is_beta());
128    }
129
130    #[test]
131    fn date() {
132        let channel = Channel::stable(RustVersion::new(1, 2, 3));
133        let mut toolchain = Toolchain::new(
134            channel,
135            None,
136            Target::host(),
137            ComponentSet::default(),
138            TargetSet::default(),
139        );
140
141        assert!(toolchain.date().is_none());
142
143        toolchain.set_date(Some(Date::new(2025, 1, 2)));
144
145        assert_eq!(toolchain.date().unwrap().year(), 2025);
146        assert_eq!(toolchain.date().unwrap().month(), 1);
147        assert_eq!(toolchain.date().unwrap().day(), 2);
148    }
149
150    #[test]
151    fn host() {
152        let channel = Channel::stable(RustVersion::new(1, 2, 3));
153        let mut toolchain = Toolchain::new(
154            channel,
155            None,
156            Target::host(),
157            ComponentSet::default(),
158            TargetSet::default(),
159        );
160
161        assert_eq!(toolchain.host(), &Target::host());
162
163        toolchain.set_host(Target::from_target_triple_or_unknown("make it unknown"));
164
165        assert_eq!(
166            toolchain.host(),
167            &Target::from_target_triple_or_unknown("make it unknown")
168        );
169    }
170
171    #[test]
172    fn components() {
173        let channel = Channel::stable(RustVersion::new(1, 2, 3));
174        let mut toolchain = Toolchain::new(
175            channel,
176            None,
177            Target::host(),
178            ComponentSet::default(),
179            TargetSet::default(),
180        );
181
182        assert!(toolchain.components().is_empty());
183
184        let set = [Component::new("hello"), Component::new("world")]
185            .into_iter()
186            .collect::<ComponentSet>();
187
188        let expected = set.clone();
189
190        toolchain.set_components(set);
191
192        assert_eq!(toolchain.components(), &expected);
193    }
194
195    #[test]
196    fn targets() {
197        let channel = Channel::stable(RustVersion::new(1, 2, 3));
198        let mut toolchain = Toolchain::new(
199            channel,
200            None,
201            Target::host(),
202            ComponentSet::default(),
203            TargetSet::default(),
204        );
205
206        assert!(toolchain.targets().is_empty());
207
208        let set = [Target::from_target_triple_or_unknown("hello")]
209            .into_iter()
210            .collect::<TargetSet>();
211
212        let expected = set.clone();
213
214        toolchain.set_targets(set);
215
216        assert_eq!(toolchain.targets(), &expected);
217    }
218
219    #[test]
220    fn a_clone_shares_the_components_and_targets_of_the_toolchain_it_was_cloned_from() {
221        let toolchain = Toolchain::new(
222            Channel::stable(RustVersion::new(1, 2, 3)),
223            None,
224            Target::host(),
225            [Component::new("cargo")].into_iter().collect(),
226            [Target::host()].into_iter().collect(),
227        );
228
229        let clone = toolchain.clone();
230
231        assert!(ptr::eq(
232            toolchain.components().as_slice(),
233            clone.components().as_slice()
234        ));
235        assert!(ptr::eq(
236            toolchain.targets().as_slice(),
237            clone.targets().as_slice()
238        ));
239    }
240}