10 /// Assemble and write blocks of data
12 /// This type implement 'TapeWrite'. Data written is assembled to
13 /// equally sized blocks (see 'BlockHeader'), which are then written
14 /// to the underlying writer.
15 pub struct BlockedWriter
<W
: BlockWrite
> {
17 buffer
: Box
<BlockHeader
>,
20 logical_end_of_media
: bool
,
25 impl <W
: BlockWrite
> Drop
for BlockedWriter
<W
> {
27 // Try to make sure to end the file with a filemark
30 let _
= self.writer
.write_filemark();
35 impl <W
: BlockWrite
> BlockedWriter
<W
> {
37 /// Allow access to underlying writer
38 pub fn writer_ref_mut(&mut self) -> &mut W
{
42 /// Creates a new instance.
43 pub fn new(writer
: W
) -> Self {
46 buffer
: BlockHeader
::new(),
49 logical_end_of_media
: false,
55 fn write_block(buffer
: &BlockHeader
, writer
: &mut W
) -> Result
<bool
, std
::io
::Error
> {
58 std
::slice
::from_raw_parts(
59 (buffer
as *const BlockHeader
) as *const u8,
63 writer
.write_block(data
)
66 fn write_eof(&mut self) -> Result
<(), std
::io
::Error
> {
68 proxmox_sys
::io_bail
!("BlockedWriter: detected multiple EOF writes");
70 self.wrote_eof
= true;
72 self.writer
.write_filemark()
75 fn write(&mut self, data
: &[u8]) -> Result
<usize, std
::io
::Error
> {
77 if data
.is_empty() { return Ok(0); }
79 let rest
= self.buffer
.payload
.len() - self.buffer_pos
;
80 let bytes
= if data
.len() < rest { data.len() }
else { rest }
;
81 self.buffer
.payload
[self.buffer_pos
..(self.buffer_pos
+bytes
)]
82 .copy_from_slice(&data
[..bytes
]);
84 let rest
= rest
- bytes
;
87 self.buffer
.flags
= BlockHeaderFlags
::empty();
88 self.buffer
.set_size(self.buffer
.payload
.len());
89 self.buffer
.set_seq_nr(self.seq_nr
);
91 let leom
= Self::write_block(&self.buffer
, &mut self.writer
)?
;
92 if leom { self.logical_end_of_media = true; }
94 self.bytes_written
+= BlockHeader
::SIZE
;
97 self.buffer_pos
+= bytes
;
105 impl <W
: BlockWrite
> TapeWrite
for BlockedWriter
<W
> {
107 fn write_all(&mut self, mut data
: &[u8]) -> Result
<bool
, std
::io
::Error
> {
108 while !data
.is_empty() {
109 match self.write(data
) {
110 Ok(n
) => data
= &data
[n
..],
111 Err(e
) => return Err(e
),
114 Ok(self.logical_end_of_media
)
117 fn bytes_written(&self) -> usize {
121 /// flush last block, set END_OF_STREAM flag
123 /// Note: This may write an empty block just including the
124 /// END_OF_STREAM flag.
125 fn finish(&mut self, incomplete
: bool
) -> Result
<bool
, std
::io
::Error
> {
126 vec
::clear(&mut self.buffer
.payload
[self.buffer_pos
..]);
127 self.buffer
.flags
= BlockHeaderFlags
::END_OF_STREAM
;
128 if incomplete { self.buffer.flags |= BlockHeaderFlags::INCOMPLETE; }
129 self.buffer
.set_size(self.buffer_pos
);
130 self.buffer
.set_seq_nr(self.seq_nr
);
132 self.bytes_written
+= BlockHeader
::SIZE
;
133 let leom
= Self::write_block(&self.buffer
, &mut self.writer
)?
;
138 /// Returns if the writer already detected the logical end of media
139 fn logical_end_of_media(&self) -> bool
{
140 self.logical_end_of_media