snix_store/pathinfoservice/nix_http/
castore_infused.rs1use nix_compat::{narinfo::NarInfo, nixhash::NixHash};
2use snix_castore::{
3 Node, blobservice::BlobService, directoryservice::DirectoryService,
4 proto::parse_infused_nar_path,
5};
6
7pub async fn try_infused_nar_path<BS, DS>(
13 narinfo: &NarInfo<'_>,
14 blob_service: BS,
15 directory_service: DS,
16) -> Result<Option<Node>, Error>
17where
18 BS: BlobService + 'static,
19 DS: DirectoryService,
20{
21 let (node, nar_size) = match parse_infused_nar_path(narinfo.url) {
22 Some(e) => e,
23 None => return Ok(None),
24 };
25
26 if nar_size != narinfo.nar_size {
27 return Err(Error::InconsistentNarSizeInURL);
28 }
29
30 let mut r =
32 crate::nar::seekable::Reader::new(node.clone(), blob_service, directory_service).await?;
33
34 let (actual_nar_hash, actual_nar_size) =
36 nix_compat::hashing::hash::<sha2::Sha256>(&mut r, tokio::io::sink()).await?;
37
38 if narinfo.nar_size != actual_nar_size {
39 return Err(Error::WrongNARSize {
40 expected: narinfo.nar_size,
41 actual: actual_nar_size,
42 });
43 }
44 if narinfo.nar_hash != actual_nar_hash.as_slice() {
45 return Err(Error::WrongNARHash {
46 expected: narinfo.nar_hash,
47 actual: actual_nar_hash.into(),
48 });
49 }
50
51 Ok(Some(node))
52}
53
54#[derive(thiserror::Error, Debug)]
55pub enum Error {
56 #[error("found infused NAR path, but with differing nar_size!")]
57 InconsistentNarSizeInURL,
58
59 #[error("failed to render NAR: {0}")]
60 RenderingNAR(#[from] crate::nar::RenderError),
61
62 #[error("failed to read NAR: {0}")]
63 IO(#[from] std::io::Error),
64
65 #[error("got unexpected NAR size while rendering NAR: {actual}, expected {expected}")]
66 WrongNARSize { expected: u64, actual: u64 },
67
68 #[error("got unexpected NAR hash while rendering NAR: {0}, expected {1}",
69 NixHash::Sha256(*actual),
70 NixHash::Sha256(*expected),
71 )]
72 WrongNARHash {
73 expected: [u8; 32],
74 actual: [u8; 32],
75 },
76}