ostree_ext/container/
layer_source.rs1use anyhow::Result;
4use containers_image_proxy::oci_spec::image as oci_image;
5use containers_image_proxy::{ConvertedLayerInfo, ImageProxy, OpenedImage, Transport};
6use futures_util::future::BoxFuture;
7use tokio::io::AsyncBufRead;
8use tokio::sync::{OnceCell, watch::Sender};
9
10use super::store::LayerProgress;
11use super::unencapsulate::fetch_layer;
12
13pub type FetchedLayer<'a> = (
18 Box<dyn AsyncBufRead + Send + Unpin>,
19 BoxFuture<'a, Result<()>>,
20 oci_image::MediaType,
21);
22
23pub trait LayerSource: std::fmt::Debug + Send + Sync {
28 fn fetch_layer<'a>(
30 &'a self,
31 manifest: &'a oci_image::ImageManifest,
32 layer: &'a oci_image::Descriptor,
33 progress: Option<&'a Sender<Option<LayerProgress>>>,
34 ) -> BoxFuture<'a, Result<FetchedLayer<'a>>>;
35
36 fn finish(self: Box<Self>) -> BoxFuture<'static, Result<()>>;
43}
44
45#[derive(Debug)]
47pub(crate) struct ProxyLayerSource {
48 proxy: ImageProxy,
49 img: OpenedImage,
50 transport: Transport,
51 layer_info: OnceCell<Option<Vec<ConvertedLayerInfo>>>,
52}
53
54impl ProxyLayerSource {
55 pub(crate) fn new(proxy: ImageProxy, img: OpenedImage, transport: Transport) -> Self {
56 Self {
57 proxy,
58 img,
59 transport,
60 layer_info: OnceCell::new(),
61 }
62 }
63}
64
65impl LayerSource for ProxyLayerSource {
66 fn fetch_layer<'a>(
67 &'a self,
68 manifest: &'a oci_image::ImageManifest,
69 layer: &'a oci_image::Descriptor,
70 progress: Option<&'a Sender<Option<LayerProgress>>>,
71 ) -> BoxFuture<'a, Result<FetchedLayer<'a>>> {
72 Box::pin(async move {
73 let layer_info = self
74 .layer_info
75 .get_or_try_init(|| self.proxy.get_layer_info(&self.img))
76 .await?;
77 let (blob, driver, media_type) = fetch_layer(
78 &self.proxy,
79 &self.img,
80 manifest,
81 layer,
82 progress,
83 layer_info.as_ref(),
84 self.transport,
85 )
86 .await?;
87 Ok((blob, Box::pin(driver) as BoxFuture<'a, _>, media_type))
88 })
89 }
90
91 fn finish(self: Box<Self>) -> BoxFuture<'static, Result<()>> {
92 Box::pin(async move {
93 let Self { proxy, img, .. } = *self;
94 proxy.close_image(&img).await?;
97 proxy.finalize().await?;
98 Ok(())
99 })
100 }
101}