1use crate::derived_path::{DerivedPath, LegacyDerivedPath};
2use crate::nixbase32;
3use crate::wire::de::Error;
4use crate::{
5 narinfo::Signature,
6 nixhash::CAHash,
7 store_path::StorePath,
8 wire::{
9 de::{NixDeserialize, NixRead},
10 ser::{NixSerialize, NixWrite},
11 },
12};
13use nix_compat_derive::{NixDeserialize, NixSerialize};
14use std::future::Future;
15
16#[derive(Clone, Debug, NixDeserialize, NixSerialize)]
18#[nix(from = "u64", into = "u64")]
19pub struct IgnoredZero;
20impl From<u64> for IgnoredZero {
21 fn from(_: u64) -> Self {
22 IgnoredZero
23 }
24}
25
26impl From<IgnoredZero> for u64 {
27 fn from(_: IgnoredZero) -> Self {
28 0
29 }
30}
31
32#[derive(Debug, NixSerialize)]
33pub struct TraceLine {
34 have_pos: IgnoredZero,
35 hint: String,
36}
37
38#[derive(NixSerialize)]
42pub struct NixError {
43 #[nix(version = "26..")]
44 type_: &'static str,
45
46 #[nix(version = "26..")]
47 level: u64,
48
49 #[nix(version = "26..")]
50 name: &'static str,
51
52 msg: String,
53 #[nix(version = "26..")]
54 have_pos: IgnoredZero,
55
56 #[nix(version = "26..")]
57 traces: Vec<TraceLine>,
58
59 #[nix(version = "..=25")]
60 exit_status: u64,
61}
62
63impl NixError {
64 pub fn new(msg: String) -> Self {
65 Self {
66 type_: "Error",
67 level: 0, name: "Error",
69 msg,
70 have_pos: IgnoredZero {},
71 traces: vec![],
72 exit_status: 1,
73 }
74 }
75}
76
77nix_compat_derive::nix_serialize_remote!(#[nix(display)] Signature<String>);
78
79impl NixDeserialize for Signature<String> {
80 async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error>
81 where
82 R: ?Sized + NixRead + Send,
83 {
84 let value: Option<String> = reader.try_read_value().await?;
85 match value {
86 Some(value) => Ok(Some(
87 Signature::<String>::parse(&value).map_err(R::Error::invalid_data)?,
88 )),
89 None => Ok(None),
90 }
91 }
92}
93
94impl NixSerialize for CAHash {
95 async fn serialize<W>(&self, writer: &mut W) -> Result<(), W::Error>
96 where
97 W: NixWrite,
98 {
99 writer.write_value(&self.to_nix_nixbase32_string()).await
100 }
101}
102
103impl NixSerialize for Option<CAHash> {
104 async fn serialize<W>(&self, writer: &mut W) -> Result<(), W::Error>
105 where
106 W: NixWrite,
107 {
108 match self {
109 Some(value) => writer.write_value(value).await,
110 None => writer.write_value("").await,
111 }
112 }
113}
114
115impl NixDeserialize for CAHash {
116 async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error>
117 where
118 R: ?Sized + NixRead + Send,
119 {
120 let value: Option<String> = reader.try_read_value().await?;
121 match value {
122 Some(value) => Ok(Some(CAHash::from_nix_hex_str(&value).ok_or_else(|| {
123 R::Error::invalid_data(format!("Invalid cahash {value}"))
124 })?)),
125 None => Ok(None),
126 }
127 }
128}
129
130impl NixDeserialize for Option<CAHash> {
131 async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error>
132 where
133 R: ?Sized + NixRead + Send,
134 {
135 let value: Option<String> = reader.try_read_value().await?;
136 match value {
137 Some(value) => {
138 if value.is_empty() {
139 Ok(None)
140 } else {
141 Ok(Some(Some(CAHash::from_nix_hex_str(&value).ok_or_else(
142 || R::Error::invalid_data(format!("Invalid cahash {value}")),
143 )?)))
144 }
145 }
146 None => Ok(None),
147 }
148 }
149}
150
151impl NixSerialize for Option<UnkeyedValidPathInfo> {
152 async fn serialize<W>(&self, writer: &mut W) -> Result<(), W::Error>
153 where
154 W: NixWrite,
155 {
156 match self {
157 Some(value) => {
158 writer.write_value(&true).await?;
159 writer.write_value(value).await
160 }
161 None => writer.write_value(&false).await,
162 }
163 }
164}
165
166impl NixDeserialize for StorePath<String> {
168 async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error>
169 where
170 R: ?Sized + NixRead + Send,
171 {
172 use crate::wire::de::Error;
173 if let Some(buf) = reader.try_read_bytes().await? {
174 let result = StorePath::<String>::from_absolute_path(&buf);
175 result.map(Some).map_err(R::Error::invalid_data)
176 } else {
177 Ok(None)
178 }
179 }
180}
181
182impl NixDeserialize for Option<StorePath<String>> {
183 async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error>
184 where
185 R: ?Sized + NixRead + Send,
186 {
187 use crate::wire::de::Error;
188 if let Some(buf) = reader.try_read_bytes().await? {
189 if buf.is_empty() {
190 Ok(Some(None))
191 } else {
192 let result = StorePath::<String>::from_absolute_path(&buf);
193 result
194 .map(|r| Some(Some(r)))
195 .map_err(R::Error::invalid_data)
196 }
197 } else {
198 Ok(Some(None))
199 }
200 }
201}
202
203impl<S> NixSerialize for StorePath<S>
205where
206 S: AsRef<str>,
207{
208 fn serialize<W>(&self, writer: &mut W) -> impl Future<Output = Result<(), W::Error>> + Send
209 where
210 W: NixWrite,
211 {
212 let fmt = self.as_absolute_path_fmt();
213 async move { writer.write_display(fmt).await }
214 }
215}
216
217nix_compat_derive::nix_serialize_remote!(
218 #[nix(into = "LegacyDerivedPath", from = "LegacyDerivedPath")]
219 DerivedPath
220);
221nix_compat_derive::nix_serialize_remote!(
222 #[nix(from_str, display)]
223 LegacyDerivedPath
224);
225
226impl NixSerialize for Option<StorePath<String>> {
228 async fn serialize<W>(&self, writer: &mut W) -> Result<(), W::Error>
229 where
230 W: NixWrite,
231 {
232 match self {
233 Some(value) => writer.write_value(value).await,
234 None => writer.write_value("").await,
235 }
236 }
237}
238
239#[derive(NixSerialize, NixDeserialize, Debug, Clone, PartialEq)]
240pub struct UnkeyedValidPathInfo {
241 pub deriver: Option<StorePath<String>>,
242 pub nar_hash: NarHash,
243 pub references: Vec<StorePath<String>>,
244 pub registration_time: u64,
245 pub nar_size: u64,
246 pub ultimate: bool,
247 pub signatures: Vec<Signature<String>>,
248 pub ca: Option<CAHash>,
249}
250
251#[derive(NixDeserialize)]
253pub struct QueryValidPaths {
254 pub paths: Vec<StorePath<String>>,
256
257 #[nix(version = "27..")]
259 pub substitute: bool,
260}
261
262#[derive(Debug, Clone, Copy, PartialEq, Eq)]
264pub struct NarHash([u8; 32]);
265
266impl NarHash {
267 pub fn from_digest(digest: [u8; 32]) -> Self {
268 NarHash(digest)
269 }
270}
271
272impl std::ops::Deref for NarHash {
273 type Target = [u8; 32];
274
275 fn deref(&self) -> &Self::Target {
276 &self.0
277 }
278}
279
280impl NixDeserialize for NarHash {
281 async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error>
282 where
283 R: ?Sized + NixRead + Send,
284 {
285 if let Some(bytes) = reader.try_read_bytes().await? {
286 let result = data_encoding::HEXLOWER
287 .decode(bytes.as_ref())
288 .map_err(R::Error::invalid_data)?;
289 Ok(Some(NarHash(result.try_into().map_err(|_| {
290 R::Error::invalid_data("incorrect length")
291 })?)))
292 } else {
293 Ok(None)
294 }
295 }
296}
297
298impl NixSerialize for NarHash {
299 async fn serialize<W>(&self, writer: &mut W) -> Result<(), W::Error>
300 where
301 W: NixWrite,
302 {
303 nixbase32::encode(&self.0).serialize(writer).await
304 }
305}
306
307#[derive(NixDeserialize, Debug)]
311pub struct ValidPathInfo {
312 pub path: StorePath<String>,
314 pub info: UnkeyedValidPathInfo,
315}