1use crate::archive::Archive;
2use crate::error::ZipErrorT;
3use crate::ffi;
4use crate::Error;
5use crate::Result;
6use std::io;
7use std::marker::PhantomData;
8use std::ptr::null_mut;
9
10#[derive(Clone, Copy, PartialEq, Eq, Hash)]
11pub enum Encoding {
12 Guess,
13 Utf8,
14 Cp437,
15}
16
17#[derive(Clone, Copy, PartialEq, Eq, Hash)]
18pub enum OpenFlag {
19 Compressed,
20 Unchanged,
21}
22
23#[derive(Clone, Copy, PartialEq, Eq, Hash)]
24pub enum LocateFlag {
25 NoCase,
26 NoDir,
27 EncodingRaw,
28 EncodingGuess,
29 EncodingStrict,
30}
31
32#[derive(Debug)]
33pub struct File<'a> {
34 pub(crate) handle: *mut ffi::zip_file_t,
35 pub(crate) phantom: PhantomData<&'a Archive>,
36}
37
38impl File<'_> {
39 fn error(&mut self) -> ZipErrorT<&mut ffi::zip_error_t> {
40 unsafe {
41 let error = ffi::zip_file_get_error(self.handle);
42 (&mut *error).into()
43 }
44 }
45
46 pub fn close(mut self) -> Result<()> {
47 if self.handle.is_null() {
48 Ok(())
49 } else {
50 let result = unsafe { ffi::zip_fclose(self.handle) };
51 self.handle = null_mut();
52 if result == 0 {
53 Ok(())
54 } else {
55 let error: ZipErrorT<_> = result.into();
56 Err(error.into())
57 }
58 }
59 }
60}
61impl Drop for File<'_> {
62 fn drop(&mut self) {
63 if !self.handle.is_null() {
64 unsafe {
65 ffi::zip_fclose(self.handle);
66 }
67 }
68 }
69}
70
71impl io::Read for File<'_> {
72 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
73 let result = unsafe { ffi::zip_fread(self.handle, buf.as_mut_ptr() as _, buf.len() as _) };
74 if result == -1 {
75 let error: Error = self.error().into();
76 Err(io::Error::new(io::ErrorKind::Other, error))
77 } else {
78 Ok(result as _)
79 }
80 }
81}
82
83impl io::Seek for File<'_> {
84 fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
85 let result = unsafe {
86 match pos {
87 io::SeekFrom::Start(pos) => {
88 ffi::zip_fseek(self.handle, pos as _, ffi::SEEK_SET as _)
89 }
90 io::SeekFrom::End(pos) => ffi::zip_fseek(self.handle, pos as _, ffi::SEEK_END as _),
91 io::SeekFrom::Current(pos) => {
92 ffi::zip_fseek(self.handle, pos as _, ffi::SEEK_CUR as _)
93 }
94 }
95 };
96 if result == -1 {
97 let error: Error = self.error().into();
98 Err(io::Error::new(io::ErrorKind::Other, error))
99 } else {
100 unsafe {
101 Ok(ffi::zip_ftell(self.handle) as _)
103 }
104 }
105 }
106}