1#![no_std]
2#![allow(non_snake_case)]
3#![allow(clippy::too_many_arguments)]
4#![deny(unreachable_pub)]
5#![deny(unsafe_op_in_unsafe_fn)]
6
7#[cfg(feature = "std")]
10extern crate std;
11
12use core::ffi::c_int;
13#[cfg(not(feature = "std"))]
14use core::sync::atomic::{AtomicI32, Ordering};
15
16mod allocator;
17mod blocksort;
18mod bzlib;
19mod compress;
20mod crctable;
21mod decompress;
22#[cfg(feature = "stdio")]
23mod high_level;
24mod huffman;
25mod randtable;
26
27pub(crate) use bzlib::{Action, ReturnCode};
28
29pub const BZ_OK: c_int = ReturnCode::BZ_OK as c_int;
30pub const BZ_RUN_OK: c_int = ReturnCode::BZ_RUN_OK as c_int;
31pub const BZ_FLUSH_OK: c_int = ReturnCode::BZ_FLUSH_OK as c_int;
32pub const BZ_FINISH_OK: c_int = ReturnCode::BZ_FINISH_OK as c_int;
33pub const BZ_STREAM_END: c_int = ReturnCode::BZ_STREAM_END as c_int;
34pub const BZ_SEQUENCE_ERROR: c_int = ReturnCode::BZ_SEQUENCE_ERROR as c_int;
35pub const BZ_PARAM_ERROR: c_int = ReturnCode::BZ_PARAM_ERROR as c_int;
36pub const BZ_MEM_ERROR: c_int = ReturnCode::BZ_MEM_ERROR as c_int;
37pub const BZ_DATA_ERROR: c_int = ReturnCode::BZ_DATA_ERROR as c_int;
38pub const BZ_DATA_ERROR_MAGIC: c_int = ReturnCode::BZ_DATA_ERROR_MAGIC as c_int;
39pub const BZ_IO_ERROR: c_int = ReturnCode::BZ_IO_ERROR as c_int;
40pub const BZ_UNEXPECTED_EOF: c_int = ReturnCode::BZ_UNEXPECTED_EOF as c_int;
41pub const BZ_OUTBUFF_FULL: c_int = ReturnCode::BZ_OUTBUFF_FULL as c_int;
42pub const BZ_CONFIG_ERROR: c_int = ReturnCode::BZ_CONFIG_ERROR as c_int;
43
44pub const BZ_RUN: c_int = Action::Run as c_int;
45pub const BZ_FLUSH: c_int = Action::Flush as c_int;
46pub const BZ_FINISH: c_int = Action::Finish as c_int;
47
48pub const BZ_MAX_UNUSED: c_int = bzlib::BZ_MAX_UNUSED_U32 as c_int;
49
50pub use bzlib::bz_stream;
52#[cfg(feature = "stdio")]
53pub use bzlib::BZFILE;
54
55pub use bzlib::{BZ2_bzCompress, BZ2_bzCompressEnd, BZ2_bzCompressInit};
57pub use bzlib::{BZ2_bzDecompress, BZ2_bzDecompressEnd, BZ2_bzDecompressInit};
58
59pub use bzlib::{BZ2_bzBuffToBuffCompress, BZ2_bzBuffToBuffDecompress};
61
62#[cfg(feature = "stdio")]
64pub use bzlib::{BZ2_bzRead, BZ2_bzReadClose, BZ2_bzReadGetUnused, BZ2_bzReadOpen};
65#[cfg(feature = "stdio")]
66pub use bzlib::{BZ2_bzWrite, BZ2_bzWriteClose, BZ2_bzWriteClose64, BZ2_bzWriteOpen};
67
68#[cfg(feature = "stdio")]
70pub use bzlib::{
71 BZ2_bzclose, BZ2_bzdopen, BZ2_bzerror, BZ2_bzflush, BZ2_bzlibVersion, BZ2_bzopen, BZ2_bzread,
72 BZ2_bzwrite,
73};
74
75macro_rules! libbz2_rs_sys_version {
78 () => {
79 concat!("1.1.0-libbz2-rs-sys-", env!("CARGO_PKG_VERSION"))
80 };
81}
82
83pub(crate) use libbz2_rs_sys_version;
84
85#[cfg(all(not(feature = "std"), feature = "stdio"))]
88pub(crate) struct StderrWritter;
89
90#[cfg(all(not(feature = "std"), feature = "stdio"))]
91impl core::fmt::Write for StderrWritter {
92 fn write_str(&mut self, s: &str) -> core::fmt::Result {
93 use core::ffi::c_void;
94 use libc::write;
95
96 unsafe { write(2, s.as_ptr() as *const c_void, s.len() as _) };
97
98 Ok(())
99 }
100}
101
102macro_rules! debug_log {
103 ($($arg:tt)*) => {
104 #[cfg(feature = "std")]
105 std::eprint!($($arg)*);
106 #[cfg(all(not(feature = "std"), feature = "stdio"))]
107 {
108 use core::fmt::Write;
109 let _ = write!($crate::StderrWritter, $($arg)*);
110 }
111 };
112}
113
114macro_rules! debug_logln {
115 ($($arg:tt)*) => {
116 #[cfg(feature = "std")]
117 std::eprintln!($($arg)*);
118 #[cfg(all(not(feature = "std"), feature = "stdio"))]
119 {
120 use core::fmt::Write;
121 let _ = writeln!($crate::StderrWritter, $($arg)*);
122 }
123 };
124}
125
126pub(crate) use debug_log;
127pub(crate) use debug_logln;
128
129macro_rules! assert_h {
132 ($condition:expr, $errcode:expr) => {
133 if !$condition {
134 $crate::handle_assert_failure($errcode)
135 }
136 };
137}
138
139#[cfg(not(feature = "std"))]
140#[doc(hidden)]
141pub static ASSERT_CODE: AtomicI32 = AtomicI32::new(-1);
142
143#[cold]
144fn handle_assert_failure(errcode: c_int) -> ! {
145 #[cfg(feature = "std")]
146 std::eprint!("{}", AssertFail(errcode));
147 #[cfg(feature = "std")]
148 std::process::exit(3);
149
150 #[cfg(not(feature = "std"))]
153 #[allow(clippy::unnecessary_cast)]
154 ASSERT_CODE.store(errcode as i32, Ordering::Relaxed);
155 #[cfg(not(feature = "std"))]
156 panic!("{}", AssertFail(errcode));
157}
158
159use assert_h;
160
161struct AssertFail(i32);
162
163impl core::fmt::Display for AssertFail {
164 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
165 write!(
166 f,
167 concat!(
168 "\n",
169 "\n",
170 "libbzip2-rs: internal error number {}.\n",
171 "This is a bug in libbzip2-rs, {}.\n",
172 "Please report it at: https://github.com/trifectatechfoundation/libbzip2-rs/issues\n",
173 "If this happened when you were using some program which uses\n",
174 "libbzip2-rs as a component, you should also report this bug to\n",
175 "the author(s) of that program.\n",
176 "Please make an effort to report this bug;\n",
177 "timely and accurate bug reports eventually lead to higher\n",
178 "quality software. Thanks.\n",
179 "\n"
180 ),
181 self.0,
182 libbz2_rs_sys_version!(),
183 )?;
184
185 if self.0 == 1007 {
186 write!(
187 f,
188 concat!(
189 "\n",
190 "*** A special note about internal error number 1007 ***\n",
191 "\n",
192 "Experience suggests that a common cause of i.e. 1007\n",
193 "is unreliable memory or other hardware. The 1007 assertion\n",
194 "just happens to cross-check the results of huge numbers of\n",
195 "memory reads/writes, and so acts (unintendedly) as a stress\n",
196 "test of your memory system.\n",
197 "\n",
198 "I suggest the following: try compressing the file again,\n",
199 "possibly monitoring progress in detail with the -vv flag.\n",
200 "\n",
201 "* If the error cannot be reproduced, and/or happens at different\n",
202 " points in compression, you may have a flaky memory system.\n",
203 " Try a memory-test program. I have used Memtest86\n",
204 " (www.memtest86.com). At the time of writing it is free (GPLd).\n",
205 " Memtest86 tests memory much more thorougly than your BIOSs\n",
206 " power-on test, and may find failures that the BIOS doesn't.\n",
207 "\n",
208 "* If the error can be repeatably reproduced, this is a bug in\n",
209 " bzip2, and I would very much like to hear about it. Please\n",
210 " let me know, and, ideally, save a copy of the file causing the\n",
211 " problem -- without which I will be unable to investigate it.\n",
212 "\n"
213 )
214 )?;
215 }
216
217 Ok(())
218 }
219}
220
221#[cfg(test)]
222mod test {
223 extern crate alloc;
224
225 use super::*;
226
227 use alloc::string::String;
228
229 #[test]
230 fn print_assert_fail_coverage() {
231 use core::fmt::Write;
232 write!(&mut String::new(), "{}", AssertFail(1007)).unwrap();
233 }
234}