use super::{Body, ResponseEncoder};
use git_zero_core::{
Error, ObjectId, Repository, Result,
cache::selected::{Key, Selection},
pack,
};
pub struct PreparedResponse<'a> {
encoder: ResponseEncoder<'a>,
pack: Option<pack::Encoder<'a>>,
key: Option<Key>,
}
impl<'a> PreparedResponse<'a> {
pub fn new(
mut encoder: ResponseEncoder<'a>,
repository: &impl Repository,
ids: &mut [ObjectId],
) -> Result<Self> {
if encoder.started || encoder.cancelled {
return Err(Error::InvalidRequest);
}
let (pack, key) = match core::mem::replace(&mut encoder.body, Body::Buffered) {
Body::Pack(pack) => {
let selection = pack.selection().map_or(Selection::All, Selection::Indices);
let key = Key::derive(repository, selection, ids)?;
(Some(pack), Some(key))
}
body => {
encoder.body = body;
(None, None)
}
};
Ok(Self { encoder, pack, key })
}
pub fn key(&self) -> Option<Key> {
self.key
}
pub fn response(&self) -> crate::Response {
self.encoder.response()
}
pub fn read_pack(&mut self, repository: &impl Repository, output: &mut [u8]) -> Result<usize> {
self.pack
.as_mut()
.ok_or(Error::InvalidRequest)?
.read(repository, output)
}
pub fn attach(
mut self,
bytes: &'a [u8],
ids: &mut [ObjectId],
byte_limit: usize,
) -> Result<ResponseEncoder<'a>> {
self.key
.ok_or(Error::InvalidRequest)?
.verify_pack(bytes, ids, byte_limit)?;
self.encoder.body = Body::Cached { bytes, position: 0 };
Ok(self.encoder)
}
pub fn without_pack(self) -> Result<ResponseEncoder<'a>> {
if self.key.is_some() {
return Err(Error::InvalidRequest);
}
Ok(self.encoder)
}
}