Struct UnitInfo

Source
pub struct UnitInfo(/* private fields */);

Implementations§

Source§

impl UnitInfo

Source

pub fn is_normal(&self) -> bool

Examples found in repository?
examples/enumerate-items.rs (line 26)
23fn describe_item(item: UnitInfo) {
24    let mut description = String::new();
25
26    if item.is_normal() {
27        description.push_str("normal ");
28    } else if item.is_special() {
29        description.push_str("special ");
30    } else if item.is_meta() {
31        description.push_str("meta ");
32    }
33
34    if item.is_dir() {
35        description.push_str("dir");
36    } else if item.is_file() {
37        description.push_str("file");
38    }
39
40    if item.length() % 7 == 0 {
41        description.push_str("🦀");
42    }
43
44    println!(
45        "   {} {:8} {:8}   {}\t\t{}",
46        item.space(),
47        item.start(),
48        item.length(),
49        description,
50        item.path().unwrap_or(Path::new("")).display()
51    );
52}
More examples
Hide additional examples
examples/extract.rs (line 30)
25fn extract(
26    root_dir: &Path,
27    file: &mut ChmFile,
28    item: &UnitInfo,
29) -> Result<(), Box<dyn Error>> {
30    if !item.is_file() || !item.is_normal() {
31        // we only care about normal files
32        return Ok(());
33    }
34    let path = match item.path() {
35        Some(p) => p,
36        // if we can't get the path, ignore it and continue
37        None => return Ok(()),
38    };
39
40    let mut dest = root_dir.to_path_buf();
41    // Note: by design, the path for a normal file is absolute (starts with "/")
42    // so when joining it with the root_dir we need to drop the initial "/".
43    dest.extend(path.components().skip(1));
44
45    // make sure the parent directory exists
46    if let Some(parent) = dest.parent() {
47        fs::create_dir_all(parent)?;
48    }
49
50    let mut f = File::create(dest)?;
51    let mut start_offset = 0;
52    // CHMLib doesn't give us a &[u8] with the file contents directly (e.g.
53    // because it may be compressed) so we need to copy chunks to an
54    // intermediate buffer
55    let mut buffer = vec![0; 1 << 16];
56
57    loop {
58        let bytes_read = file.read(item, start_offset, &mut buffer)?;
59        if bytes_read == 0 {
60            // we've reached the end of the file
61            break;
62        } else {
63            // write this chunk to the file and continue
64            start_offset += bytes_read as u64;
65            f.write_all(&buffer)?;
66        }
67    }
68
69    Ok(())
70}
Source

pub fn is_special(&self) -> bool

Examples found in repository?
examples/enumerate-items.rs (line 28)
23fn describe_item(item: UnitInfo) {
24    let mut description = String::new();
25
26    if item.is_normal() {
27        description.push_str("normal ");
28    } else if item.is_special() {
29        description.push_str("special ");
30    } else if item.is_meta() {
31        description.push_str("meta ");
32    }
33
34    if item.is_dir() {
35        description.push_str("dir");
36    } else if item.is_file() {
37        description.push_str("file");
38    }
39
40    if item.length() % 7 == 0 {
41        description.push_str("🦀");
42    }
43
44    println!(
45        "   {} {:8} {:8}   {}\t\t{}",
46        item.space(),
47        item.start(),
48        item.length(),
49        description,
50        item.path().unwrap_or(Path::new("")).display()
51    );
52}
Source

pub fn is_meta(&self) -> bool

Examples found in repository?
examples/enumerate-items.rs (line 30)
23fn describe_item(item: UnitInfo) {
24    let mut description = String::new();
25
26    if item.is_normal() {
27        description.push_str("normal ");
28    } else if item.is_special() {
29        description.push_str("special ");
30    } else if item.is_meta() {
31        description.push_str("meta ");
32    }
33
34    if item.is_dir() {
35        description.push_str("dir");
36    } else if item.is_file() {
37        description.push_str("file");
38    }
39
40    if item.length() % 7 == 0 {
41        description.push_str("🦀");
42    }
43
44    println!(
45        "   {} {:8} {:8}   {}\t\t{}",
46        item.space(),
47        item.start(),
48        item.length(),
49        description,
50        item.path().unwrap_or(Path::new("")).display()
51    );
52}
Source

pub fn is_file(&self) -> bool

Examples found in repository?
examples/enumerate-items.rs (line 36)
23fn describe_item(item: UnitInfo) {
24    let mut description = String::new();
25
26    if item.is_normal() {
27        description.push_str("normal ");
28    } else if item.is_special() {
29        description.push_str("special ");
30    } else if item.is_meta() {
31        description.push_str("meta ");
32    }
33
34    if item.is_dir() {
35        description.push_str("dir");
36    } else if item.is_file() {
37        description.push_str("file");
38    }
39
40    if item.length() % 7 == 0 {
41        description.push_str("🦀");
42    }
43
44    println!(
45        "   {} {:8} {:8}   {}\t\t{}",
46        item.space(),
47        item.start(),
48        item.length(),
49        description,
50        item.path().unwrap_or(Path::new("")).display()
51    );
52}
More examples
Hide additional examples
examples/extract.rs (line 30)
25fn extract(
26    root_dir: &Path,
27    file: &mut ChmFile,
28    item: &UnitInfo,
29) -> Result<(), Box<dyn Error>> {
30    if !item.is_file() || !item.is_normal() {
31        // we only care about normal files
32        return Ok(());
33    }
34    let path = match item.path() {
35        Some(p) => p,
36        // if we can't get the path, ignore it and continue
37        None => return Ok(()),
38    };
39
40    let mut dest = root_dir.to_path_buf();
41    // Note: by design, the path for a normal file is absolute (starts with "/")
42    // so when joining it with the root_dir we need to drop the initial "/".
43    dest.extend(path.components().skip(1));
44
45    // make sure the parent directory exists
46    if let Some(parent) = dest.parent() {
47        fs::create_dir_all(parent)?;
48    }
49
50    let mut f = File::create(dest)?;
51    let mut start_offset = 0;
52    // CHMLib doesn't give us a &[u8] with the file contents directly (e.g.
53    // because it may be compressed) so we need to copy chunks to an
54    // intermediate buffer
55    let mut buffer = vec![0; 1 << 16];
56
57    loop {
58        let bytes_read = file.read(item, start_offset, &mut buffer)?;
59        if bytes_read == 0 {
60            // we've reached the end of the file
61            break;
62        } else {
63            // write this chunk to the file and continue
64            start_offset += bytes_read as u64;
65            f.write_all(&buffer)?;
66        }
67    }
68
69    Ok(())
70}
Source

pub fn is_dir(&self) -> bool

Examples found in repository?
examples/enumerate-items.rs (line 34)
23fn describe_item(item: UnitInfo) {
24    let mut description = String::new();
25
26    if item.is_normal() {
27        description.push_str("normal ");
28    } else if item.is_special() {
29        description.push_str("special ");
30    } else if item.is_meta() {
31        description.push_str("meta ");
32    }
33
34    if item.is_dir() {
35        description.push_str("dir");
36    } else if item.is_file() {
37        description.push_str("file");
38    }
39
40    if item.length() % 7 == 0 {
41        description.push_str("🦀");
42    }
43
44    println!(
45        "   {} {:8} {:8}   {}\t\t{}",
46        item.space(),
47        item.start(),
48        item.length(),
49        description,
50        item.path().unwrap_or(Path::new("")).display()
51    );
52}
Source

pub fn space(&self) -> c_int

Examples found in repository?
examples/enumerate-items.rs (line 46)
23fn describe_item(item: UnitInfo) {
24    let mut description = String::new();
25
26    if item.is_normal() {
27        description.push_str("normal ");
28    } else if item.is_special() {
29        description.push_str("special ");
30    } else if item.is_meta() {
31        description.push_str("meta ");
32    }
33
34    if item.is_dir() {
35        description.push_str("dir");
36    } else if item.is_file() {
37        description.push_str("file");
38    }
39
40    if item.length() % 7 == 0 {
41        description.push_str("🦀");
42    }
43
44    println!(
45        "   {} {:8} {:8}   {}\t\t{}",
46        item.space(),
47        item.start(),
48        item.length(),
49        description,
50        item.path().unwrap_or(Path::new("")).display()
51    );
52}
Source

pub fn start(&self) -> u64

The starting position within the underlying file.

Examples found in repository?
examples/enumerate-items.rs (line 47)
23fn describe_item(item: UnitInfo) {
24    let mut description = String::new();
25
26    if item.is_normal() {
27        description.push_str("normal ");
28    } else if item.is_special() {
29        description.push_str("special ");
30    } else if item.is_meta() {
31        description.push_str("meta ");
32    }
33
34    if item.is_dir() {
35        description.push_str("dir");
36    } else if item.is_file() {
37        description.push_str("file");
38    }
39
40    if item.length() % 7 == 0 {
41        description.push_str("🦀");
42    }
43
44    println!(
45        "   {} {:8} {:8}   {}\t\t{}",
46        item.space(),
47        item.start(),
48        item.length(),
49        description,
50        item.path().unwrap_or(Path::new("")).display()
51    );
52}
Source

pub fn length(&self) -> u64

The number of bytes in this item.

Examples found in repository?
examples/enumerate-items.rs (line 40)
23fn describe_item(item: UnitInfo) {
24    let mut description = String::new();
25
26    if item.is_normal() {
27        description.push_str("normal ");
28    } else if item.is_special() {
29        description.push_str("special ");
30    } else if item.is_meta() {
31        description.push_str("meta ");
32    }
33
34    if item.is_dir() {
35        description.push_str("dir");
36    } else if item.is_file() {
37        description.push_str("file");
38    }
39
40    if item.length() % 7 == 0 {
41        description.push_str("🦀");
42    }
43
44    println!(
45        "   {} {:8} {:8}   {}\t\t{}",
46        item.space(),
47        item.start(),
48        item.length(),
49        description,
50        item.path().unwrap_or(Path::new("")).display()
51    );
52}
Source

pub fn path(&self) -> Option<&Path>

The item’s filename.

§Security

This path is provided by the original CHM file’s author. It is the caller’s responsibility to handle malicious input (e.g. /../../../etc/passwd).

Examples found in repository?
examples/enumerate-items.rs (line 50)
23fn describe_item(item: UnitInfo) {
24    let mut description = String::new();
25
26    if item.is_normal() {
27        description.push_str("normal ");
28    } else if item.is_special() {
29        description.push_str("special ");
30    } else if item.is_meta() {
31        description.push_str("meta ");
32    }
33
34    if item.is_dir() {
35        description.push_str("dir");
36    } else if item.is_file() {
37        description.push_str("file");
38    }
39
40    if item.length() % 7 == 0 {
41        description.push_str("🦀");
42    }
43
44    println!(
45        "   {} {:8} {:8}   {}\t\t{}",
46        item.space(),
47        item.start(),
48        item.length(),
49        description,
50        item.path().unwrap_or(Path::new("")).display()
51    );
52}
More examples
Hide additional examples
examples/extract.rs (line 34)
25fn extract(
26    root_dir: &Path,
27    file: &mut ChmFile,
28    item: &UnitInfo,
29) -> Result<(), Box<dyn Error>> {
30    if !item.is_file() || !item.is_normal() {
31        // we only care about normal files
32        return Ok(());
33    }
34    let path = match item.path() {
35        Some(p) => p,
36        // if we can't get the path, ignore it and continue
37        None => return Ok(()),
38    };
39
40    let mut dest = root_dir.to_path_buf();
41    // Note: by design, the path for a normal file is absolute (starts with "/")
42    // so when joining it with the root_dir we need to drop the initial "/".
43    dest.extend(path.components().skip(1));
44
45    // make sure the parent directory exists
46    if let Some(parent) = dest.parent() {
47        fs::create_dir_all(parent)?;
48    }
49
50    let mut f = File::create(dest)?;
51    let mut start_offset = 0;
52    // CHMLib doesn't give us a &[u8] with the file contents directly (e.g.
53    // because it may be compressed) so we need to copy chunks to an
54    // intermediate buffer
55    let mut buffer = vec![0; 1 << 16];
56
57    loop {
58        let bytes_read = file.read(item, start_offset, &mut buffer)?;
59        if bytes_read == 0 {
60            // we've reached the end of the file
61            break;
62        } else {
63            // write this chunk to the file and continue
64            start_offset += bytes_read as u64;
65            f.write_all(&buffer)?;
66        }
67    }
68
69    Ok(())
70}

Trait Implementations§

Source§

impl Debug for UnitInfo

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.