1use std::collections::BTreeMap;
2use std::time::Duration;
3
4use crate::derived_path::DerivedPath;
5use crate::nixbase32;
6use crate::realisation::{DrvOutput, Realisation};
7use crate::wire::de::Error;
8use crate::{
9 narinfo::Signature,
10 nixhash::CAHash,
11 store_path::StorePath,
12 wire::{
13 de::{NixDeserialize, NixRead},
14 ser::{NixSerialize, NixWrite},
15 },
16};
17use bytes::Bytes;
18use nix_compat_derive::{NixDeserialize, NixSerialize};
19
20#[derive(Clone, Debug, NixDeserialize, NixSerialize)]
22#[nix(from = "u64", into = "u64")]
23pub struct IgnoredZero;
24impl From<u64> for IgnoredZero {
25 fn from(_: u64) -> Self {
26 IgnoredZero
27 }
28}
29
30impl From<IgnoredZero> for u64 {
31 fn from(_: IgnoredZero) -> Self {
32 0
33 }
34}
35
36#[derive(
37 Debug,
38 Clone,
39 Copy,
40 PartialEq,
41 Eq,
42 PartialOrd,
43 Ord,
44 Hash,
45 num_enum::TryFromPrimitive,
46 num_enum::IntoPrimitive,
47 NixDeserialize,
48 NixSerialize,
49)]
50#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
51#[nix(try_from = "u16", into = "u16")]
52#[repr(u16)]
53pub enum BuildMode {
54 Normal = 0,
55 Repair = 1,
56 Check = 2,
57}
58
59#[derive(
60 Debug,
61 Clone,
62 Copy,
63 PartialEq,
64 Eq,
65 PartialOrd,
66 Ord,
67 Hash,
68 num_enum::TryFromPrimitive,
69 num_enum::IntoPrimitive,
70 NixDeserialize,
71 NixSerialize,
72)]
73#[nix(try_from = "u16", into = "u16")]
74#[repr(u16)]
75pub enum BuildStatus {
76 Built = 0,
77 Substituted = 1,
78 AlreadyValid = 2,
79 PermanentFailure = 3,
80 InputRejected = 4,
81 OutputRejected = 5,
82 TransientFailure = 6,
83 CachedFailure = 7,
84 TimedOut = 8,
85 MiscFailure = 9,
86 DependencyFailed = 10,
87 LogLimitExceeded = 11,
88 NotDeterministic = 12,
89 ResolvesToAlreadyValid = 13,
90 NoSubstituters = 14,
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, NixDeserialize, NixSerialize)]
94#[repr(transparent)]
95pub struct Microseconds(i64);
96
97impl From<i64> for Microseconds {
98 fn from(value: i64) -> Self {
99 Microseconds(value)
100 }
101}
102
103impl From<Microseconds> for Duration {
104 fn from(value: Microseconds) -> Self {
105 Duration::from_micros(value.0.unsigned_abs())
106 }
107}
108
109impl TryFrom<Duration> for Microseconds {
110 type Error = std::num::TryFromIntError;
111 fn try_from(value: Duration) -> Result<Self, Self::Error> {
112 Ok(Microseconds(value.as_micros().try_into()?))
113 }
114}
115
116impl From<Microseconds> for i64 {
117 fn from(value: Microseconds) -> Self {
118 value.0
119 }
120}
121
122impl NixDeserialize for Option<Microseconds> {
123 async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error>
124 where
125 R: ?Sized + NixRead + Send,
126 {
127 if let Some(tag) = reader.try_read_value::<u8>().await? {
128 match tag {
129 0 => Ok(Some(None)),
130 1 => Ok(Some(Some(reader.read_value::<Microseconds>().await?))),
131 _ => Err(R::Error::invalid_data("invalid optional tag from remote")),
132 }
133 } else {
134 Ok(None)
135 }
136 }
137}
138
139impl NixSerialize for Option<Microseconds> {
140 async fn serialize<W>(&self, writer: &mut W) -> Result<(), W::Error>
141 where
142 W: NixWrite,
143 {
144 if let Some(value) = self.as_ref() {
145 writer.write_number(1).await?;
146 writer.write_value(value).await
147 } else {
148 writer.write_number(0).await
149 }
150 }
151}
152
153#[derive(Debug, NixSerialize)]
154pub struct TraceLine {
155 have_pos: IgnoredZero,
156 hint: String,
157}
158
159#[derive(NixSerialize)]
163pub struct NixError {
164 #[nix(version = "26..")]
165 type_: &'static str,
166
167 #[nix(version = "26..")]
168 level: u64,
169
170 #[nix(version = "26..")]
171 name: &'static str,
172
173 msg: String,
174 #[nix(version = "26..")]
175 have_pos: IgnoredZero,
176
177 #[nix(version = "26..")]
178 traces: Vec<TraceLine>,
179
180 #[nix(version = "..=25")]
181 exit_status: u64,
182}
183
184impl NixError {
185 pub fn new(msg: String) -> Self {
186 Self {
187 type_: "Error",
188 level: 0, name: "Error",
190 msg,
191 have_pos: IgnoredZero {},
192 traces: vec![],
193 exit_status: 1,
194 }
195 }
196}
197
198impl NixSerialize for Option<UnkeyedValidPathInfo> {
199 async fn serialize<W>(&self, writer: &mut W) -> Result<(), W::Error>
200 where
201 W: NixWrite,
202 {
203 match self {
204 Some(value) => {
205 writer.write_value(&true).await?;
206 writer.write_value(value).await
207 }
208 None => writer.write_value(&false).await,
209 }
210 }
211}
212
213#[derive(NixSerialize, NixDeserialize, Debug, Clone, PartialEq)]
214pub struct UnkeyedValidPathInfo {
215 pub deriver: Option<StorePath>,
216 pub nar_hash: NarHash,
217 pub references: Vec<StorePath>,
218 pub registration_time: u64,
219 pub nar_size: u64,
220 pub ultimate: bool,
221 pub signatures: Vec<Signature<String>>,
222 pub ca: Option<CAHash>,
223}
224
225#[derive(NixDeserialize)]
227pub struct QueryValidPaths {
228 pub paths: Vec<StorePath>,
230
231 #[nix(version = "27..")]
233 pub substitute: bool,
234}
235
236#[derive(NixDeserialize)]
238pub struct BuildPaths {
239 pub paths: Vec<DerivedPath>,
241
242 pub mode: BuildMode,
244}
245
246#[derive(Debug, Clone, Copy, PartialEq, Eq)]
248pub struct NarHash([u8; 32]);
249
250impl NarHash {
251 pub fn from_digest(digest: [u8; 32]) -> Self {
252 NarHash(digest)
253 }
254}
255
256impl std::ops::Deref for NarHash {
257 type Target = [u8; 32];
258
259 fn deref(&self) -> &Self::Target {
260 &self.0
261 }
262}
263
264impl NixDeserialize for NarHash {
265 async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error>
266 where
267 R: ?Sized + NixRead + Send,
268 {
269 if let Some(bytes) = reader.try_read_bytes().await? {
270 let result = data_encoding::HEXLOWER
271 .decode(bytes.as_ref())
272 .map_err(R::Error::invalid_data)?;
273 Ok(Some(NarHash(result.try_into().map_err(|_| {
274 R::Error::invalid_data("incorrect length")
275 })?)))
276 } else {
277 Ok(None)
278 }
279 }
280}
281
282impl NixSerialize for NarHash {
283 async fn serialize<W>(&self, writer: &mut W) -> Result<(), W::Error>
284 where
285 W: NixWrite,
286 {
287 nixbase32::encode(&self.0).serialize(writer).await
288 }
289}
290
291#[derive(NixDeserialize, Debug)]
295pub struct ValidPathInfo {
296 pub path: StorePath,
298 pub info: UnkeyedValidPathInfo,
299}
300
301#[derive(Debug, Clone, PartialEq, Eq, NixDeserialize, NixSerialize)]
302pub struct BuildResult {
303 pub status: BuildStatus,
304 pub error_msg: Bytes,
305 #[nix(version = "29..")]
306 pub times_built: u32,
307 #[nix(version = "29..")]
308 pub is_non_deterministic: bool,
309 #[nix(version = "29..")]
310 pub start_time: u64,
311 #[nix(version = "29..")]
312 pub stop_time: u64,
313 #[nix(version = "37..")]
314 pub cpu_user: Option<Microseconds>,
315 #[nix(version = "37..")]
316 pub cpu_system: Option<Microseconds>,
317 #[nix(version = "28..")]
318 pub built_outputs: BTreeMap<DrvOutput, Realisation>,
319}
320
321pub type KeyedBuildResults = Vec<KeyedBuildResult>;
322#[derive(Debug, Clone, PartialEq, Eq, NixDeserialize, NixSerialize)]
323pub struct KeyedBuildResult {
324 pub path: DerivedPath,
325 pub result: BuildResult,
326}
327
328#[derive(Debug, Clone, PartialEq, Eq, Hash, NixDeserialize, NixSerialize)]
329pub struct QueryMissingResult {
330 pub will_build: Vec<StorePath>,
331 pub will_substitute: Vec<StorePath>,
332 pub unknown: Vec<StorePath>,
333 pub download_size: u64,
334 pub nar_size: u64,
335}