1#[cfg(feature = "serde")]
2use crate::nixhash;
3use crate::{narinfo::SignatureRef, store_path::StorePathRef};
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6use std::collections::BTreeSet;
7
8#[derive(Clone, Debug, Eq, PartialEq, Hash)]
14#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15pub struct ExportedPathInfo<'a> {
16 #[cfg_attr(feature = "serde", serde(rename = "closureSize"))]
17 pub closure_size: u64,
18
19 #[cfg_attr(
20 feature = "serde",
21 serde(
22 rename = "narHash",
23 serialize_with = "nixhash::serde::to_nix_nixbase32",
24 deserialize_with = "nixhash::serde::from_nix_nixbase32_or_sri"
25 )
26 )]
27 pub nar_sha256: [u8; 32],
28
29 #[cfg_attr(feature = "serde", serde(rename = "narSize"))]
30 pub nar_size: u64,
31
32 #[cfg_attr(feature = "serde", serde(borrow))]
33 pub path: StorePathRef<'a>,
34
35 #[cfg_attr(
36 feature = "serde",
37 serde(borrow, skip_serializing_if = "Option::is_none")
38 )]
39 pub deriver: Option<StorePathRef<'a>>,
40
41 pub references: BTreeSet<StorePathRef<'a>>,
44 #[cfg_attr(
47 feature = "serde",
48 serde(default, skip_serializing_if = "Vec::is_empty")
49 )]
50 pub signatures: Vec<SignatureRef<'a>>,
51}
52
53impl Ord for ExportedPathInfo<'_> {
55 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
56 self.path.cmp(&other.path)
57 }
58}
59
60impl PartialOrd for ExportedPathInfo<'_> {
61 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
62 Some(self.cmp(other))
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 #[cfg(feature = "serde")]
69 use hex_literal::hex;
70
71 #[cfg(feature = "serde")]
72 use super::*;
73
74 #[cfg(feature = "serde")]
76 #[test]
77 fn serialize_deserialize() {
78 let pathinfos_str_json = r#"[{"closureSize":1828984,"narHash":"sha256:11vm2x1ajhzsrzw7lsyss51mmr3b6yll9wdjn51bh7liwkpc8ila","narSize":1828984,"path":"/nix/store/7n0mbqydcipkpbxm24fab066lxk68aqk-libunistring-1.1","references":["/nix/store/7n0mbqydcipkpbxm24fab066lxk68aqk-libunistring-1.1"]},{"closureSize":32696176,"narHash":"sha256:0alzbhjxdcsmr1pk7z0bdh46r2xpq3xs3k9y82bi4bx5pklcvw5x","narSize":226560,"path":"/nix/store/dbghhbq1x39yxgkv3vkgfwbxrmw9nfzi-hello-2.12.1","references":["/nix/store/dbghhbq1x39yxgkv3vkgfwbxrmw9nfzi-hello-2.12.1","/nix/store/ddwyrxif62r8n6xclvskjyy6szdhvj60-glibc-2.39-5"]},{"closureSize":32469616,"narHash":"sha256:1zw5p05fh0k836ybfxkskv8apcv2m3pm2wa6y90wqn5w5kjyj13c","narSize":30119936,"path":"/nix/store/ddwyrxif62r8n6xclvskjyy6szdhvj60-glibc-2.39-5","references":["/nix/store/ddwyrxif62r8n6xclvskjyy6szdhvj60-glibc-2.39-5","/nix/store/rxganm4ibf31qngal3j3psp20mak37yy-xgcc-13.2.0-libgcc","/nix/store/s32cldbh9pfzd9z82izi12mdlrw0yf8q-libidn2-2.3.7"]},{"closureSize":159560,"narHash":"sha256:10q8iyvfmpfck3yiisnj1j8vp6lq3km17r26sr95zpdf9mgmk69s","narSize":159560,"path":"/nix/store/rxganm4ibf31qngal3j3psp20mak37yy-xgcc-13.2.0-libgcc","references":[]},{"closureSize":2190120,"narHash":"sha256:1cv997nzxbd91jhmzwnhxa1ahlzp5ffli8m4a5npcq8zg0vb1kwg","narSize":361136,"path":"/nix/store/s32cldbh9pfzd9z82izi12mdlrw0yf8q-libidn2-2.3.7","references":["/nix/store/7n0mbqydcipkpbxm24fab066lxk68aqk-libunistring-1.1","/nix/store/s32cldbh9pfzd9z82izi12mdlrw0yf8q-libidn2-2.3.7"]}]"#;
81
82 let deserialized: BTreeSet<ExportedPathInfo> =
84 serde_json::from_str(pathinfos_str_json).expect("must serialize");
85
86 let serialized_again = serde_json::to_string(&deserialized).expect("must deserialize");
87 assert_eq!(pathinfos_str_json, serialized_again);
88
89 assert_eq!(
91 &ExportedPathInfo {
92 closure_size: 1828984,
93 nar_sha256: hex!(
94 "8a46c4eee4911eb842b1b2f144a9376be45a43d1da6b7af8cffa43a942177587"
95 ),
96 nar_size: 1828984,
97 path: StorePathRef::from_bytes(
98 b"7n0mbqydcipkpbxm24fab066lxk68aqk-libunistring-1.1"
99 )
100 .expect("must parse"),
101 deriver: None,
102 references: BTreeSet::from_iter([StorePathRef::from_bytes(
103 b"7n0mbqydcipkpbxm24fab066lxk68aqk-libunistring-1.1"
104 )
105 .unwrap()]),
106 signatures: vec![],
107 },
108 deserialized.first().unwrap()
109 );
110 }
111
112 #[cfg(feature = "serde")]
114 #[test]
115 fn serialize_deserialize_from_path_info() {
116 let pathinfos_str_json = r#"[{"closureSize":10756176,"deriver":"/nix/store/vs9976cyyxpykvdnlv7x85fpp3shn6ij-libcxx-16.0.6.drv","narHash":"sha256-E73Nt0NAKGxCnsyBFDUaCAbA+wiF5qjq1O9J7WrnT0E=","narSize":7020664,"path":"/nix/store/z6r3bn5l51679pwkvh9nalp6c317z34m-libcxx-16.0.6-dev","references":["/nix/store/lzzd5jgybnpfj86xkcpnd54xgwc4m457-libcxx-16.0.6"],"registrationTime":1730048276,"signatures":["cache.nixos.org-1:cTdhK6hnpPwtMXFX43CYb7v+CbpAusVI/MORZ3v5aHvpBYNg1MfBHVVeoexMBpNtHA8uFAn0aEsJaLXYIDhJDg=="],"valid":true}]"#;
119
120 let deserialized: BTreeSet<ExportedPathInfo> =
121 serde_json::from_str(pathinfos_str_json).expect("must serialize");
122
123 assert_eq!(
124 &ExportedPathInfo {
125 closure_size: 10756176,
126 nar_sha256: hex!(
127 "13bdcdb74340286c429ecc8114351a0806c0fb0885e6a8ead4ef49ed6ae74f41"
128 ),
129 nar_size: 7020664,
130 path: StorePathRef::from_bytes(
131 b"z6r3bn5l51679pwkvh9nalp6c317z34m-libcxx-16.0.6-dev"
132 )
133 .expect("must parse"),
134 deriver: Some(
135 StorePathRef::from_bytes(
136 b"vs9976cyyxpykvdnlv7x85fpp3shn6ij-libcxx-16.0.6.drv"
137 )
138 .expect("must parse")
139 ),
140 references: BTreeSet::from_iter([StorePathRef::from_bytes(
141 b"lzzd5jgybnpfj86xkcpnd54xgwc4m457-libcxx-16.0.6"
142 )
143 .unwrap()]),
144 signatures: vec![SignatureRef::parse("cache.nixos.org-1:cTdhK6hnpPwtMXFX43CYb7v+CbpAusVI/MORZ3v5aHvpBYNg1MfBHVVeoexMBpNtHA8uFAn0aEsJaLXYIDhJDg==").expect("must parse")],
145 },
146 deserialized.first().unwrap()
147 );
148 }
149}