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