mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-01-13 07:53:22 -05:00
add some comments to Slices
This commit is contained in:
parent
8e499aa070
commit
eb4221851e
@ -28,19 +28,31 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Tools for implementing a `resource::Resource` body composed from many "slices".
|
||||||
|
|
||||||
use error::{Error, Result};
|
use error::{Error, Result};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
|
/// Information needed by `Slices` about a single slice.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SliceInfo<W> {
|
struct SliceInfo<W> {
|
||||||
|
/// The byte position (relative to the start of the `Slices`) beyond the end of this slice.
|
||||||
|
/// Note the starting position (and thus length) are inferred from the previous slice.
|
||||||
end: u64,
|
end: u64,
|
||||||
|
|
||||||
|
/// Should be an implementation of `ContextWriter<Ctx>` for some `Ctx`.
|
||||||
writer: W,
|
writer: W,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Writes a byte range to the given `io::Write` given a context argument; meant for use with
|
||||||
|
/// `Slices`.
|
||||||
pub trait ContextWriter<Ctx> {
|
pub trait ContextWriter<Ctx> {
|
||||||
|
/// Writes `r` to `out`, as in `resource::Resource::write_to`.
|
||||||
|
/// The additional argument `ctx` is as supplied to the `Slices`.
|
||||||
|
/// The additional argument `l` is the length of this slice, as determined by the `Slices`.
|
||||||
fn write_to(&self, ctx: &Ctx, r: Range<u64>, l: u64, out: &mut io::Write) -> Result<()>;
|
fn write_to(&self, ctx: &Ctx, r: Range<u64>, l: u64, out: &mut io::Write) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,13 +71,22 @@ where F: FnMut(&mut Vec<u8>) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Slices<W, C> {
|
/// Helper to serve byte ranges from a body which is broken down into many "slices".
|
||||||
|
/// This is used to implement `.mp4` serving in `mp4::Mp4File` from `mp4::Mp4FileSlice` enums.
|
||||||
|
pub struct Slices<W, C> where W: ContextWriter<C> {
|
||||||
|
/// The total byte length of the `Slices`.
|
||||||
|
/// Equivalent to `self.slices.back().map(|s| s.end).unwrap_or(0)`; kept for convenience and to
|
||||||
|
/// avoid a branch.
|
||||||
len: u64,
|
len: u64,
|
||||||
|
|
||||||
|
/// 0 or more slices of this file.
|
||||||
slices: Vec<SliceInfo<W>>,
|
slices: Vec<SliceInfo<W>>,
|
||||||
|
|
||||||
|
/// Marker so that `C` is part of the type.
|
||||||
phantom: PhantomData<C>,
|
phantom: PhantomData<C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W, C> fmt::Debug for Slices<W, C> where W: fmt::Debug {
|
impl<W, C> fmt::Debug for Slices<W, C> where W: fmt::Debug + ContextWriter<C> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{} slices with overall length {}:", self.slices.len(), self.len)?;
|
write!(f, "{} slices with overall length {}:", self.slices.len(), self.len)?;
|
||||||
let mut start = 0;
|
let mut start = 0;
|
||||||
@ -83,10 +104,12 @@ impl<W, C> Slices<W, C> where W: ContextWriter<C> {
|
|||||||
Slices{len: 0, slices: Vec::new(), phantom: PhantomData}
|
Slices{len: 0, slices: Vec::new(), phantom: PhantomData}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reserves space for at least `additional` more slices to be appended.
|
||||||
pub fn reserve(&mut self, additional: usize) {
|
pub fn reserve(&mut self, additional: usize) {
|
||||||
self.slices.reserve(additional)
|
self.slices.reserve(additional)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Appends the given slice.
|
||||||
pub fn append(&mut self, len: u64, writer: W) {
|
pub fn append(&mut self, len: u64, writer: W) {
|
||||||
self.len += len;
|
self.len += len;
|
||||||
self.slices.push(SliceInfo{end: self.len, writer: writer});
|
self.slices.push(SliceInfo{end: self.len, writer: writer});
|
||||||
@ -98,8 +121,9 @@ impl<W, C> Slices<W, C> where W: ContextWriter<C> {
|
|||||||
/// Returns the number of slices.
|
/// Returns the number of slices.
|
||||||
pub fn num(&self) -> usize { self.slices.len() }
|
pub fn num(&self) -> usize { self.slices.len() }
|
||||||
|
|
||||||
pub fn write_to(&self, ctx: &C, range: Range<u64>, out: &mut io::Write)
|
/// Writes `range` to `out`.
|
||||||
-> Result<()> {
|
/// This interface mirrors `resource::Resource::write_to`, with the additional `ctx` argument.
|
||||||
|
pub fn write_to(&self, ctx: &C, range: Range<u64>, out: &mut io::Write) -> Result<()> {
|
||||||
if range.start > range.end || range.end > self.len {
|
if range.start > range.end || range.end > self.len {
|
||||||
return Err(Error{
|
return Err(Error{
|
||||||
description: format!("Bad range {:?} for slice of length {}", range, self.len),
|
description: format!("Bad range {:?} for slice of length {}", range, self.len),
|
||||||
@ -116,6 +140,7 @@ impl<W, C> Slices<W, C> where W: ContextWriter<C> {
|
|||||||
Err(i) => (i, self.slices[i-1].end), // desired start < slice i's end; first is i.
|
Err(i) => (i, self.slices[i-1].end), // desired start < slice i's end; first is i.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// There is at least one slice to write.
|
||||||
// Iterate through and write each slice until the end.
|
// Iterate through and write each slice until the end.
|
||||||
let mut start_pos = range.start - slice_start;
|
let mut start_pos = range.start - slice_start;
|
||||||
loop {
|
loop {
|
||||||
@ -126,7 +151,7 @@ impl<W, C> Slices<W, C> where W: ContextWriter<C> {
|
|||||||
}
|
}
|
||||||
s.writer.write_to(ctx, start_pos .. s.end - slice_start, l, out)?;
|
s.writer.write_to(ctx, start_pos .. s.end - slice_start, l, out)?;
|
||||||
|
|
||||||
// setup next iteration.
|
// Setup next iteration.
|
||||||
start_pos = 0;
|
start_pos = 0;
|
||||||
slice_start = s.end;
|
slice_start = s.end;
|
||||||
i += 1;
|
i += 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user