snix_store/nar/narcalculationservice/
mod.rs1use auto_impl::auto_impl;
2use nix_compat::nixhash::Sha256Digester;
3use snix_castore::{Node, blobservice::BlobService, directoryservice::DirectoryService};
4use tokio_util::io::InspectWriter;
5use tonic::async_trait;
6
7use crate::{nar::write_nar, pathinfoservice};
8
9#[cfg_attr(any(test, feature = "mocks"), mockall::automock)]
10#[async_trait]
11#[auto_impl(&, &mut, Arc, Box)]
12pub trait NarCalculationService: Send + Sync {
13 async fn calculate_nar(
16 &self,
17 root_node: &Node,
18 ) -> Result<(u64, [u8; 32]), pathinfoservice::Error>;
19}
20
21pub struct Renderer<BS, DS> {
24 blob_service: BS,
25 directory_service: DS,
26}
27
28impl<BS, DS> Renderer<BS, DS> {
29 pub fn new(blob_service: BS, directory_service: DS) -> Self {
30 Self {
31 blob_service,
32 directory_service,
33 }
34 }
35}
36
37#[async_trait]
38impl<BS, DS> NarCalculationService for Renderer<BS, DS>
39where
40 BS: BlobService,
41 DS: DirectoryService,
42{
43 async fn calculate_nar(
44 &self,
45 root_node: &Node,
46 ) -> Result<(u64, [u8; 32]), pathinfoservice::Error> {
47 let mut digester = Sha256Digester::new();
49
50 let mut nar_size = 0;
51 let writer = InspectWriter::new(tokio::io::sink(), |data| {
52 nar_size += data.len() as u64;
53 digester.update(data);
54 });
55
56 write_nar(
57 writer,
58 root_node,
59 &self.blob_service,
60 &self.directory_service,
61 )
62 .await?;
63
64 Ok((nar_size, digester.finalize().into()))
65 }
66}