blob: b15fa5ab692ca2c4aff6d5c3a348f78145b7e3b1 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::range::ContentRange;
use crate::repository::Error;
use crate::util::read_stream_to_end;
use bytes::Bytes;
use fidl_fuchsia_pkg_ext::RepositoryConfig;
use futures::future::ready;
use futures::stream::{once, BoxStream, StreamExt};
use std::io;
/// [Resource] represents some resource as a stream of [Bytes] as provided from
/// a repository server.
pub struct Resource {
/// The range in bytes available for this resource.
pub content_range: ContentRange,
/// A stream of bytes representing the resource.
pub stream: BoxStream<'static, io::Result<Bytes>>,
}
impl Resource {
/// The length of the content in bytes in the stream. This may be smaller than the total length
/// of the file.
pub fn content_len(&self) -> u64 {
self.content_range.content_len()
}
/// The total length of the file range in bytes. This may be larger than the bytes in the stream.
pub fn total_len(&self) -> u64 {
self.content_range.total_len()
}
pub async fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<(), Error> {
buf.reserve(self.content_len() as usize);
read_stream_to_end(&mut self.stream, buf).await.map_err(Error::Io)
}
}
impl std::fmt::Debug for Resource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("resource")
.field("content_range", &self.content_range)
.field("stream", &"..")
.finish()
}
}
impl TryFrom<RepositoryConfig> for Resource {
type Error = Error;
fn try_from(config: RepositoryConfig) -> Result<Resource, Error> {
let json = Bytes::from(serde_json::to_vec(&config).map_err(|e| anyhow::anyhow!(e))?);
let complete_len = json.len() as u64;
Ok(Resource {
content_range: ContentRange::Full { complete_len },
stream: once(ready(Ok(json))).boxed(),
})
}
}