Skip to main content

nix_compat/nix_daemon/
types.rs

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/// Marker type that consumes/sends and ignores a u64.
23#[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/// Represents an error returned by the nix-daemon to its client.
162///
163/// Adheres to the format described in serialization.md
164#[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, // error
191            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/// Request tuple for [super::worker_protocol::Operation::QueryValidPaths]
228#[derive(NixDeserialize)]
229pub struct QueryValidPaths {
230    // Paths to query
231    pub paths: Vec<StorePath>,
232
233    // Whether to try and substitute the paths.
234    #[nix(version = "27..")]
235    pub substitute: bool,
236}
237
238/// Request tuple for [super::worker_protocol::Operation::BuildPaths]
239#[derive(NixDeserialize)]
240pub struct BuildPaths {
241    // Paths to build
242    pub paths: Vec<DerivedPath>,
243
244    // How to build the paths
245    pub mode: BuildMode,
246}
247
248/// newtype wrapper for the byte array that correctly implements NixSerialize, NixDeserialize.
249#[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/// Info type used by [super::worker_protocol::Operation::AddToStoreNar] and [super::worker_protocol::Operation::AddMultipleToStore]
294///
295/// See: [ValidPathInfo reference](https://snix.dev/docs/reference/nix-daemon-protocol/types/#validpathinfo)
296#[derive(NixDeserialize, Debug)]
297pub struct ValidPathInfo {
298    // - path :: [StorePath][se-StorePath]
299    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}