mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 00:43:24 +00:00
Change the type of iterator for cpio-decoder
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
7326eb87a0
commit
9606119028
@ -2,12 +2,12 @@
|
|||||||
//!
|
//!
|
||||||
//! # Example
|
//! # Example
|
||||||
//!
|
//!
|
||||||
//! ```rust,should_panic
|
//! ```rust
|
||||||
//! use cpio_decoder::CpioDecoder;
|
//! use cpio_decoder::CpioDecoder;
|
||||||
//!
|
//!
|
||||||
//! let decoder = CpioDecoder::new(&[]);
|
//! let decoder = CpioDecoder::new(&[]);
|
||||||
//! for entry in decoder.entries() {
|
//! for entry_result in decoder.decode_entries() {
|
||||||
//! println!("{:?}", entry);
|
//! println!("The entry_result is: {:?}", entry_result);
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
@ -41,18 +41,19 @@ impl<'a> CpioDecoder<'a> {
|
|||||||
Self { buffer }
|
Self { buffer }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return an iterator for all entries in the CPIO.
|
/// Return an iterator trying to decode the entries in the CPIO.
|
||||||
///
|
pub fn decode_entries(&'a self) -> CpioEntryIter<'a> {
|
||||||
/// It will panic if fails to decode some entries.
|
|
||||||
pub fn entries(&'a self) -> CpioEntryIter<'a> {
|
|
||||||
CpioEntryIter::new(self)
|
CpioEntryIter::new(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A file entry iterator.
|
/// An iterator over the results of CPIO entries.
|
||||||
|
///
|
||||||
|
/// It stops if reaches to the trailer entry or encounters an error.
|
||||||
pub struct CpioEntryIter<'a> {
|
pub struct CpioEntryIter<'a> {
|
||||||
buffer: &'a [u8],
|
buffer: &'a [u8],
|
||||||
offset: usize,
|
offset: usize,
|
||||||
|
is_error: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CpioEntryIter<'a> {
|
impl<'a> CpioEntryIter<'a> {
|
||||||
@ -60,20 +61,38 @@ impl<'a> CpioEntryIter<'a> {
|
|||||||
Self {
|
Self {
|
||||||
buffer: decoder.buffer,
|
buffer: decoder.buffer,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
|
is_error: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for CpioEntryIter<'a> {
|
impl<'a> Iterator for CpioEntryIter<'a> {
|
||||||
type Item = CpioEntry<'a>;
|
type Item = Result<CpioEntry<'a>>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<CpioEntry<'a>> {
|
fn next(&mut self) -> Option<Result<CpioEntry<'a>>> {
|
||||||
let entry = CpioEntry::new(&self.buffer[self.offset..]).unwrap();
|
// Stop to iterate entries if encounters an error.
|
||||||
if entry.is_trailer() {
|
if self.is_error {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
self.offset += entry.archive_offset();
|
|
||||||
Some(entry)
|
let entry_result = if self.offset >= self.buffer.len() {
|
||||||
|
Err(Error::BufferShortError)
|
||||||
|
} else {
|
||||||
|
CpioEntry::new(&self.buffer[self.offset..])
|
||||||
|
};
|
||||||
|
match &entry_result {
|
||||||
|
Ok(entry) => {
|
||||||
|
// A correct CPIO buffer must end with a trailer.
|
||||||
|
if entry.is_trailer() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
self.offset += entry.archive_offset();
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
self.is_error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(entry_result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use super::error::*;
|
||||||
use super::{CpioDecoder, FileType};
|
use super::{CpioDecoder, FileType};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -24,8 +25,10 @@ fn test_decoder() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let decoder = CpioDecoder::new(&buffer);
|
let decoder = CpioDecoder::new(&buffer);
|
||||||
assert!(decoder.entries().count() > 3);
|
assert!(decoder.decode_entries().count() > 3);
|
||||||
for (idx, entry) in decoder.entries().enumerate() {
|
for (idx, entry_result) in decoder.decode_entries().enumerate() {
|
||||||
|
assert!(entry_result.is_ok());
|
||||||
|
let entry = entry_result.unwrap();
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
assert!(entry.name() == ".");
|
assert!(entry.name() == ".");
|
||||||
assert!(entry.metadata().file_type() == FileType::Dir);
|
assert!(entry.metadata().file_type() == FileType::Dir);
|
||||||
@ -43,3 +46,22 @@ fn test_decoder() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_short_buffer() {
|
||||||
|
let decoder = CpioDecoder::new(&[]);
|
||||||
|
for entry_result in decoder.decode_entries() {
|
||||||
|
assert!(entry_result.is_err());
|
||||||
|
assert!(entry_result.err() == Some(Error::BufferShortError));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_invalid_buffer() {
|
||||||
|
let buffer: &[u8] = b"invalidmagic.invalidmagic.invalidmagic.invalidmagic.invalidmagic.invalidmagic.invalidmagic.invalidmagic.invalidmagic.invalidmagic";
|
||||||
|
let decoder = CpioDecoder::new(buffer);
|
||||||
|
for entry_result in decoder.decode_entries() {
|
||||||
|
assert!(entry_result.is_err());
|
||||||
|
assert!(entry_result.err() == Some(Error::MagicError));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user