Skip to main content

fuchsia_repo/
resource.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::range::ContentRange;
6use crate::repository::Error;
7use crate::util::read_stream_to_end;
8use bytes::Bytes;
9use fidl_fuchsia_pkg_ext::RepositoryConfig;
10use futures::future::ready;
11use futures::stream::{BoxStream, StreamExt, once};
12use std::io;
13
14/// [Resource] represents some resource as a stream of [Bytes] as provided from
15/// a repository server.
16pub struct Resource {
17    /// The range in bytes available for this resource.
18    pub content_range: ContentRange,
19
20    /// A stream of bytes representing the resource.
21    pub stream: BoxStream<'static, io::Result<Bytes>>,
22}
23
24impl Resource {
25    /// The length of the content in bytes in the stream. This may be smaller than the total length
26    /// of the file.
27    pub fn content_len(&self) -> u64 {
28        self.content_range.content_len()
29    }
30
31    /// The total length of the file range in bytes. This may be larger than the bytes in the stream.
32    pub fn total_len(&self) -> u64 {
33        self.content_range.total_len()
34    }
35
36    pub async fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<(), Error> {
37        buf.reserve(self.content_len() as usize);
38        read_stream_to_end(&mut self.stream, buf).await.map_err(Error::Io)
39    }
40}
41
42impl std::fmt::Debug for Resource {
43    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44        f.debug_struct("resource")
45            .field("content_range", &self.content_range)
46            .field("stream", &"..")
47            .finish()
48    }
49}
50
51impl TryFrom<RepositoryConfig> for Resource {
52    type Error = Error;
53
54    fn try_from(config: RepositoryConfig) -> Result<Resource, Error> {
55        let json = Bytes::from(serde_json::to_vec(&config).map_err(|e| anyhow::anyhow!(e))?);
56        let complete_len = json.len() as u64;
57        Ok(Resource {
58            content_range: ContentRange::Full { complete_len },
59            stream: once(ready(Ok(json))).boxed(),
60        })
61    }
62}