1pub mod headers;
48pub mod record;
49pub use crate::headers::MobiMetadata;
50pub(crate) mod book;
51pub(crate) mod compression;
52pub(crate) mod reader;
53pub(crate) mod writer;
54
55use compression::huff;
56use headers::{Compression, Encryption, Language, MobiType, TextEncoding};
57pub(crate) use reader::Reader;
58use record::{RawRecord, RawRecords};
59pub(crate) use writer::Writer;
60
61#[cfg(feature = "time")]
62use chrono::NaiveDateTime;
63use std::{fs::File, io, io::BufReader, ops::Range, path::Path};
64use thiserror::Error;
65
66pub type MobiResult<T> = std::result::Result<T, MobiError>;
67
68#[derive(Debug, Error)]
69pub enum MobiError {
70 #[error(transparent)]
71 IoError(#[from] std::io::Error),
72 #[error(transparent)]
73 MetadataParseError(#[from] headers::MetadataParseError),
74 #[error(transparent)]
75 DecodeError(#[from] record::DecodeError),
76 #[error(transparent)]
77 HuffmanError(#[from] huff::HuffmanError),
78}
79
80#[derive(Debug, Default)]
81pub struct Mobi {
83 pub content: Vec<u8>,
84 pub metadata: MobiMetadata,
85}
86
87impl Mobi {
88 pub fn new<B: AsRef<Vec<u8>>>(bytes: B) -> MobiResult<Mobi> {
90 Mobi::from_reader(&mut Reader::new(std::io::Cursor::new(bytes.as_ref())))
91 }
92
93 pub fn from_path<P: AsRef<Path>>(file_path: P) -> MobiResult<Mobi> {
95 let mut reader = Reader::new(BufReader::new(File::open(file_path)?));
96 Mobi::from_reader(&mut reader)
97 }
98
99 pub fn from_read<R: io::Read>(reader: R) -> MobiResult<Mobi> {
101 Mobi::from_reader(&mut Reader::new(reader))
102 }
103
104 fn from_reader<R: io::Read>(reader: &mut Reader<R>) -> MobiResult<Mobi> {
105 let metadata = MobiMetadata::from_reader(reader)?;
106 Ok(Mobi {
107 content: {
108 let mut buf = vec![0; reader.position()];
109 reader.read_to_end(&mut buf)?;
110 buf
111 },
112 metadata,
113 })
114 }
115
116 #[allow(dead_code)]
117 fn write(&self, writer: &mut impl io::Write) -> io::Result<()> {
118 let mut w = Writer::new(writer);
119
120 self.metadata.write_into(&mut w)?;
121
122 let first_offset = self.metadata.records.records[1].offset as usize;
123 let fill = first_offset - w.bytes_written();
124 w.write_be(vec![0; fill])?;
125 w.write_be(&self.content[first_offset..])
127 }
128
129 pub fn author(&self) -> Option<String> {
131 self.metadata.author()
132 }
133
134 pub fn publisher(&self) -> Option<String> {
136 self.metadata.publisher()
137 }
138
139 pub fn description(&self) -> Option<String> {
141 self.metadata.description()
142 }
143
144 pub fn isbn(&self) -> Option<String> {
146 self.metadata.isbn()
147 }
148
149 pub fn publish_date(&self) -> Option<String> {
151 self.metadata.publish_date()
152 }
153
154 pub fn contributor(&self) -> Option<String> {
156 self.metadata.contributor()
157 }
158
159 pub fn title(&self) -> String {
161 self.metadata.title()
162 }
163
164 pub fn text_encoding(&self) -> TextEncoding {
166 self.metadata.text_encoding()
167 }
168
169 pub fn mobi_type(&self) -> MobiType {
171 self.metadata.mobi_type()
172 }
173
174 pub fn language(&self) -> Language {
176 self.metadata.language()
177 }
178
179 #[cfg(feature = "time")]
180 pub fn created_datetime(&self) -> NaiveDateTime {
183 self.metadata.created_datetime()
184 }
185
186 #[cfg(feature = "time")]
187 pub fn mod_datetime(&self) -> NaiveDateTime {
190 self.metadata.mod_datetime()
191 }
192
193 #[cfg(not(feature = "time"))]
194 pub fn created_time(&self) -> u32 {
196 self.metadata.created_time()
197 }
198
199 #[cfg(not(feature = "time"))]
200 pub fn mod_time(&self) -> u32 {
202 self.metadata.mod_time()
203 }
204
205 pub fn compression(&self) -> Compression {
207 self.metadata.compression()
208 }
209 pub fn encryption(&self) -> Encryption {
211 self.metadata.encryption()
212 }
213
214 pub fn readable_records_range(&self) -> Range<usize> {
217 self.metadata.mobi.first_content_record as usize
218 ..self.metadata.mobi.first_non_book_index as usize
219 }
220
221 pub fn raw_records(&self) -> RawRecords {
223 self.metadata.records.parse(&self.content)
224 }
225
226 pub fn image_records(&self) -> Vec<RawRecord> {
228 self.raw_records()
229 .range(self.metadata.mobi.first_image_index as usize..)
230 .iter()
231 .copied()
232 .filter(|record| record.is_image_record())
233 .collect()
234 }
235
236 fn palmdoc_string_lossy(&self) -> String {
237 let encoding = self.text_encoding();
238 self.raw_records()
239 .range(self.readable_records_range())
240 .iter()
241 .map(|record| record.decompress_palmdoc().to_string_lossy(encoding))
242 .collect()
243 }
244
245 fn palmdoc_string(&self) -> MobiResult<String> {
246 let encoding = self.text_encoding();
247 let mut s = String::new();
248
249 for record in self.raw_records().range(self.readable_records_range()) {
250 let content = record.decompress_palmdoc().to_string(encoding)?;
251 s.push_str(&content);
252 }
253 Ok(s)
254 }
255
256 fn no_compression_string_lossy(&self) -> String {
257 let encoding = self.text_encoding();
258 self.raw_records()
259 .range(self.readable_records_range())
260 .iter()
261 .map(|r| record::content_to_string_lossy(r.content, encoding))
262 .collect()
263 }
264
265 fn no_compression_string(&self) -> MobiResult<String> {
266 let encoding = self.text_encoding();
267 let mut s = String::new();
268 for record in self.raw_records().range(self.readable_records_range()) {
269 let content = record::content_to_string(record.content, encoding)?;
270 s.push_str(&content);
271 }
272 Ok(s)
273 }
274
275 fn huff_data(&self) -> MobiResult<Vec<Vec<u8>>> {
276 let records = self.raw_records();
277 let huff_start = self.metadata.mobi.first_huff_record as usize;
278 let huff_count = self.metadata.mobi.huff_record_count as usize;
279 let huffs: Vec<_> = records
280 .range(huff_start..huff_start + huff_count)
281 .iter()
282 .map(|record| record.content)
283 .collect();
284
285 let sections: Vec<_> = records
286 .range(self.readable_records_range())
287 .iter()
288 .map(|record| record.content)
289 .collect();
290
291 Ok(huff::decompress(&huffs, §ions)?)
292 }
293
294 fn huff_string_lossy(&self) -> MobiResult<String> {
295 let encoding = self.text_encoding();
296 let mut s = String::new();
297 let data = self.huff_data()?;
298
299 for section in data {
300 let content = record::content_to_string_lossy(§ion, encoding);
301 s.push_str(&content);
302 }
303 Ok(s)
304 }
305
306 fn huff_string(&self) -> MobiResult<String> {
307 let encoding = self.text_encoding();
308 let mut s = String::new();
309 let data = self.huff_data()?;
310
311 for section in data {
312 let content = record::content_to_string(§ion, encoding)?;
313 s.push_str(&content);
314 }
315 Ok(s)
316 }
317
318 pub fn content_as_string_lossy(&self) -> String {
322 match self.compression() {
323 Compression::No => self.no_compression_string_lossy(),
324 Compression::PalmDoc => self.palmdoc_string_lossy(),
325 Compression::Huff => self.huff_string_lossy().unwrap_or_default(),
326 }
327 }
328
329 pub fn content_as_string(&self) -> MobiResult<String> {
333 match self.compression() {
334 Compression::No => self.no_compression_string(),
335 Compression::PalmDoc => self.palmdoc_string(),
336 Compression::Huff => self.huff_string(),
337 }
338 }
339}
340
341#[cfg(test)]
342mod test {
343 use super::*;
344 #[test]
345 fn test_no_records() {
346 let bytes = [
347 173, 21, 58, 173, 252, 173, 173, 173, 173, 173, 173, 173, 165, 173, 173, 173, 0, 0, 0,
348 255, 255, 255, 255, 255, 255, 255, 139, 0, 0, 0, 0, 0, 0, 50, 3, 0, 0, 0, 0, 0, 0, 0,
349 0, 0, 50, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
350 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
351 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
352 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
353 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
354 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
355 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
356 0, 0, 0, 0, 0, 0, 0, 231, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 173, 173, 173, 173, 0, 0, 0, 0,
357 0, 0, 0, 173, 173, 173, 33, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 0,
358 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
359 0, 0, 0, 0, 0, 70, 70, 70, 70, 70, 70, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
360 173, 162, 162, 162, 173, 173, 84, 255,
361 ];
362 assert!(Mobi::new(bytes.to_vec()).is_err());
363 }
364
365 #[test]
366 fn test_backwards_cursor_1() {
367 let bytes = [
368 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 21, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
369 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
370 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
371 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
372 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 236, 0, 0, 3, 0, 173, 173, 173,
373 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 162, 162, 162, 173, 162,
374 255, 255, 255, 5, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0,
375 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 121, 121, 121, 121, 121, 121,
376 121, 121, 121, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244,
377 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 3, 0, 0, 0, 0, 0,
378 0, 0, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244,
379 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 121, 121, 0, 193,
380 0, 0, 0, 0, 0, 65, 0, 0, 64, 0, 0, 0, 0, 0, 0, 10,
381 ];
382 assert!(Mobi::new(bytes.to_vec()).is_err());
383 }
384
385 #[test]
386 fn test_backwards_cursor_2() {
387 let bytes = [
388 0, 0, 0, 0, 0, 0, 0, 198, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
389 0, 50, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 3,
390 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
391 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 0, 2, 0, 0, 0, 0, 0,
392 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0,
393 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
394 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
395 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
396 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
397 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
398 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
399 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0,
400 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 0, 2, 0, 0, 0, 0, 193, 2, 0, 0, 0,
401 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,
402 ];
403 assert!(Mobi::new(bytes.to_vec()).is_err());
404 }
405
406 #[test]
407 fn test_offset_mismatch() {
408 let bytes = [
409 0, 0, 0, 0, 0, 0, 50, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 3, 0, 0, 0, 0, 0, 0, 0, 0,
410 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
411 0, 0, 0, 0, 0, 0, 0, 0, 231, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
412 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
413 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
414 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
415 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
416 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 231, 0,
417 2, 0, 0, 0, 0, 193, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
418 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
419 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 3, 0, 0,
420 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
421 0, 0, 0, 0, 0, 0, 193, 0, 0, 0, 0, 0, 65, 0, 0, 0, 62, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0,
422 0, 0, 0, 10,
423 ];
424 assert!(Mobi::new(bytes.to_vec()).is_err());
425 }
426
427 #[test]
428 fn test_offset_overflow() {
429 let bytes = [
430 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255,
431 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
432 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
433 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0,
434 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0,
435 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
436 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
437 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255,
438 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 65, 0,
439 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
440 0, 193, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
441 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
442 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
443 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
444 255, 255, 255, 255, 255, 255, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
445 255, 255, 255, 255, 255, 255, 255, 255, 245, 255, 255, 255, 255, 255, 255, 255, 255,
446 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
447 255, 255, 255, 255, 255, 255, 255, 255, 255, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,
448 ];
449 assert!(Mobi::new(bytes.to_vec()).is_err());
450 }
451
452 #[test]
453 fn test_small_record() {
454 let bytes = [
455 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
456 50, 3, 128, 0, 0, 0, 0, 0, 0, 0, 0, 50, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 3, 0, 0,
457 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
458 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 231, 0, 2, 0, 0, 0, 0, 0, 0,
459 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 65, 65, 65, 65, 65, 65, 65,
460 65, 0, 0, 0, 0, 0, 0, 50, 3, 128, 0, 0, 0, 0, 0, 0, 0, 0, 50, 3, 0, 0, 0, 0, 0, 0, 0,
461 0, 0, 0, 50, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 65, 65, 65, 65, 65, 65, 65,
462 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
463 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
464 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
465 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 0,
466 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 231, 0, 2, 0, 0, 0, 0,
467 193, 0, 0, 0, 254, 255, 0, 173, 173, 173, 173, 0, 0, 0, 0, 0, 0, 0, 173, 173, 173, 33,
468 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48,
469 48, 48, 48, 48, 48, 48, 48, 49, 0, 10,
470 ];
471 assert!(Mobi::new(bytes.to_vec()).is_err());
472 }
473
474 #[test]
475 fn test_subtract_overflow() {
476 let bytes = [
477 211, 147, 90, 255, 64, 255, 211, 211, 211, 88, 84, 77, 79, 66, 73, 77, 79, 66, 73, 10,
478 1, 23, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 211, 10, 211, 61, 45, 84, 69, 88,
479 84, 77, 79, 66, 73, 10, 20, 0, 0, 0, 0, 0, 0, 0, 10, 211, 61, 45, 84, 69, 88, 84, 77,
480 79, 66, 73, 77, 79, 66, 73, 10, 1, 23, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255,
481 211, 10, 211, 61, 45, 84, 69, 88, 84, 77, 79, 66, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
482 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
483 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
484 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
485 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 20, 0, 0, 248, 255,
486 255, 255, 23, 0, 0, 0, 0, 0, 0, 0, 211, 61, 45, 84, 69, 88, 84, 77, 79, 66, 73, 79, 66,
487 73, 10, 1, 23, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 211, 10, 211, 61, 45, 84,
488 69, 88, 84, 77, 79, 66, 73, 10, 20, 0, 0, 77, 79, 66, 73, 211, 147, 90, 255, 64, 255,
489 211, 211, 9, 0, 0, 0, 0, 0, 0, 0, 211, 10, 211, 211, 10, 1, 255, 0, 188, 255, 211, 1,
490 23, 0, 0, 0, 0, 0, 0, 10, 20, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
491 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
492 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
493 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
494 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 10, 211, 61, 45, 84, 69, 88, 84, 77, 79, 66, 73,
495 77, 79, 66, 73, 10, 1, 23, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 211, 0, 255,
496 255, 255, 255, 255, 211, 10, 211, 61, 45, 84, 69, 88, 84, 77, 79, 66, 73, 10, 20, 0, 0,
497 248, 255, 255, 255, 211, 61, 45, 84, 69, 88, 84, 77, 79, 66, 73, 77, 79, 66, 73, 10, 1,
498 255, 0, 188, 255, 211, 10, 211, 61, 45, 84, 69, 10, 211, 61, 45, 84, 69, 79, 75,
499 ];
500 assert!(Mobi::new(bytes.to_vec()).is_err());
501 }
502
503 #[test]
504 fn test_read_out_of_bounds() {
505 let bytes = [
506 211, 147, 90, 255, 64, 255, 211, 211, 211, 10, 211, 211, 211, 255, 255, 255, 255, 255,
507 211, 10, 211, 61, 45, 84, 69, 88, 84, 1, 0, 0, 0, 188, 128, 255, 42, 0, 211, 207, 147,
508 90, 255, 64, 255, 211, 211, 211, 10, 211, 211, 108, 255, 255, 255, 255, 255, 211, 10,
509 211, 61, 45, 84, 69, 88, 84, 77, 79, 66, 73, 77, 79, 66, 73, 10, 1, 23, 0, 0, 0, 0, 0,
510 0, 0, 255, 255, 0, 0, 0, 159, 10, 211, 61, 211, 255, 69, 88, 84, 77, 79, 66, 73, 0, 0,
511 0, 232, 10, 20, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 211, 147, 90, 255,
512 64, 255, 211, 211, 211, 88, 84, 77, 79, 66, 73, 77, 79, 66, 73, 10, 1, 23, 0, 0, 0, 0,
513 0, 0, 0, 255, 255, 255, 255, 255, 211, 10, 211, 61, 45, 84, 69, 88, 84, 77, 79, 66, 73,
514 10, 20, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
515 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 0, 0, 66, 73, 10, 1, 255, 0,
516 211, 1, 23, 84, 69, 88, 84, 0, 0, 0, 0, 0, 0, 10, 20, 0, 255, 255, 255, 255, 255, 255,
517 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
518 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
519 255, 255, 255, 35, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
520 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
521 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 255, 0,
522 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
523 255, 255, 255, 255, 255, 255, 255, 248, 255, 255, 255, 211, 61, 45, 84, 69, 88, 84, 77,
524 1, 0, 0, 0, 0, 0, 0, 1, 79, 66, 73, 77, 79, 66, 255, 255, 255, 255, 211, 0, 255, 255,
525 255, 255, 0, 188, 73, 10, 1, 255, 0, 188, 255, 211, 1, 23, 0, 0, 0, 0, 0, 0, 0, 255,
526 255, 255, 255, 255, 211, 10, 211, 61, 45, 84, 69, 88, 84, 77, 79, 66, 73, 10, 20, 0, 0,
527 248, 255, 255, 255, 211, 61, 255, 211, 10, 211, 61, 45, 84, 69, 10, 211, 45, 84, 69,
528 88, 84, 77, 79, 66, 73, 77, 79, 66, 61, 45, 84, 73, 10, 1, 255, 0, 188, 255, 211, 10,
529 69, 211, 61, 45, 84, 69, 10, 211, 61, 45, 84, 69, 79, 79, 75, 75,
530 ];
531 assert!(Mobi::new(bytes.to_vec()).is_err());
532 }
533
534 #[test]
535 fn test_overflowing_record() {
536 let bytes = [
537 211, 147, 90, 255, 64, 255, 211, 211, 211, 88, 84, 77, 79, 66, 73, 77, 79, 66, 2, 0, 0,
538 0, 73, 10, 1, 23, 0, 0, 0, 0, 0, 0, 77, 79, 66, 2, 0, 0, 0, 73, 10, 1, 23, 0, 0, 0,
539 255, 255, 255, 22, 255, 255, 255, 255, 255, 211, 10, 211, 61, 45, 84, 69, 88, 84, 77,
540 79, 66, 73, 10, 20, 0, 0, 0, 0, 0, 0, 0, 10, 211, 61, 45, 84, 69, 88, 93, 77, 79, 66,
541 73, 77, 79, 66, 73, 10, 1, 23, 0, 11, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 211, 10, 211,
542 61, 45, 255, 211, 10, 211, 61, 45, 84, 69, 88, 84, 77, 79, 66, 73, 10, 20, 0, 0, 0, 0,
543 0, 0, 0, 10, 211, 61, 45, 84, 69, 88, 84, 93, 79, 66, 73, 77, 79, 66, 73, 84, 77, 79,
544 66, 2, 0, 0, 0, 73, 10, 1, 0, 10, 20, 0, 255, 255, 255, 255, 45, 84, 69, 88, 84, 77,
545 79, 66, 73, 0, 0, 0, 255, 255, 255, 22, 255, 255, 255, 255, 255, 211, 10, 211, 61, 45,
546 84, 69, 88, 84, 77, 79, 66, 73, 10, 20, 0, 0, 0, 0, 0, 0, 0, 10, 211, 61, 45, 84, 69,
547 88, 93, 77, 79, 66, 73, 77, 79, 66, 73, 10, 1, 23, 0, 11, 0, 0, 0, 0, 0, 0, 0, 255,
548 255, 211, 61, 45, 255, 211, 10, 211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
549 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
550 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
551 0, 0, 0, 0, 0, 61, 45, 84, 69, 88, 84, 77, 79, 66, 73, 10, 20, 0, 0, 0, 0, 0, 0, 0, 10,
552 211, 61, 45, 84, 69, 88, 84, 93, 79, 66, 73, 77, 79, 66, 73, 84, 77, 79, 66, 2, 0, 0,
553 0, 73, 10, 1, 0, 10, 20, 0, 255, 255, 255, 255, 45, 84, 69, 88, 84, 77, 79, 66, 73,
554 179, 176, 189, 182, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
555 255, 75, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
556 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
557 255, 255, 255, 255, 255, 255, 255, 255, 10, 1, 255, 0, 230, 230, 230, 230, 230, 230,
558 230, 0, 0, 255, 255, 255, 255, 255, 211, 10, 211, 61, 45, 255, 211, 10, 211, 0, 0, 0,
559 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
560 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0,
561 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 45, 84, 69, 88, 84, 77,
562 79, 66, 73, 10, 20, 0, 0, 0, 0, 0, 0, 0, 10, 211, 61, 45, 84, 69, 88, 84, 93, 79, 66,
563 73, 77, 79, 66, 73, 84, 77, 79, 66, 2, 0, 0, 0, 73, 10, 1, 0, 10, 20, 0, 255, 255, 255,
564 255, 45, 84, 69, 88, 84, 77, 79, 66, 73, 179, 176, 189, 182, 255, 255, 255, 255, 255,
565 255, 255, 255, 255, 255, 255, 255, 255, 255, 75, 255, 255, 255, 255, 255, 255, 255,
566 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
567 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 179, 176, 189, 182, 255, 255,
568 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
569 255, 255, 79, 66, 0, 0, 0, 0, 0, 0, 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
570 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
571 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
572 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
573 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 230, 230, 230,
574 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
575 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0, 0, 255, 255, 255, 255, 255, 211,
576 10, 211, 61, 45, 255, 211, 10, 211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
577 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
578 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
579 0, 0, 0, 0, 0, 61, 45, 84, 69, 88, 84, 77, 79, 66, 73, 10, 20, 0, 0, 0, 0, 0, 0, 0, 10,
580 211, 61, 45, 84, 69, 88, 84, 93, 79, 66, 73, 77, 79, 66, 73, 84, 77, 79, 66, 2, 0, 0,
581 0, 73, 10, 1, 0, 10, 20, 0, 255, 255, 255, 255, 45, 84, 69, 88, 84, 77, 79, 66, 73,
582 179, 176, 189, 182, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
583 255, 75, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
584 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
585 255, 255, 255, 255, 255, 255, 255, 255, 10, 1, 255, 0, 188, 255, 61, 45, 84, 69, 0, 0,
586 0, 0, 0, 0, 0, 0, 0, 39, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
587 230, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 79, 75,
588 ];
589 assert!(Mobi::new(bytes.to_vec()).is_err());
590 }
591
592 #[test]
593 fn test_set_position_oom() {
594 let bytes = [
595 242, 242, 242, 242, 242, 242, 84, 80, 90, 55, 242, 242, 242, 242, 242, 242, 242, 242,
596 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 130, 62, 178, 126, 126, 126, 126,
597 130, 9, 68, 82, 77, 73, 79, 78, 238, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
598 126, 126, 126, 126, 126, 126, 84, 69, 88, 84, 82, 69, 65, 68, 126, 126, 126, 126, 242,
599 136, 126, 1, 0, 8, 242, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
600 15, 15, 15, 15, 15, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 84, 69,
601 255, 255, 255, 255, 9, 0, 0, 0, 0, 0, 0, 0, 255, 126, 126, 126, 126, 126, 126, 126,
602 126, 242, 0, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 84, 69, 88, 84, 82, 69,
603 65, 68, 82, 175, 130, 129, 129, 77, 79, 66, 73, 0, 0, 0, 232, 122, 126, 255, 255, 255,
604 255, 255, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
605 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
606 15, 15, 1, 69, 88, 84, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
607 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
608 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
609 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
610 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
611 15, 15, 15, 15, 15, 15, 15, 15, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
612 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
613 255, 255, 255, 48, 126, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
614 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
615 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 247,
616 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
617 84, 69, 255, 255, 255, 255, 255, 255, 40, 255, 255, 255, 255, 255, 255, 126, 126, 126,
618 126, 126, 93, 92, 92, 92, 92, 92, 92, 92, 163, 163, 163, 163, 163, 212, 163, 163, 163,
619 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
620 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
621 ];
622 assert!(Mobi::new(bytes.to_vec()).is_err());
623 }
624
625 #[test]
626 fn test_records_ascending() {
627 let bytes = [
628 242, 242, 242, 242, 242, 242, 84, 80, 90, 51, 242, 242, 242, 242, 242, 242, 242, 242,
629 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 130, 62, 178, 126, 126, 126, 126,
630 130, 9, 68, 82, 77, 73, 79, 248, 2, 0, 0, 0, 0, 0, 0, 126, 126, 126, 126, 126, 126,
631 126, 126, 126, 126, 84, 69, 88, 84, 82, 69, 65, 68, 126, 126, 250, 126, 242, 136, 126,
632 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247,
633 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 247, 84, 69,
634 255, 255, 255, 255, 255, 255, 255, 255, 127, 255, 255, 255, 255, 126, 126, 126, 126,
635 126, 126, 126, 126, 242, 0, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 84, 69,
636 88, 84, 82, 69, 65, 68, 82, 175, 130, 129, 129, 77, 79, 66, 73, 0, 0, 0, 232, 122, 0,
637 0, 4, 228, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
638 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 253, 0, 0,
639 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
640 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
641 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
642 96, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
643 255, 255, 255, 255, 255, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 146, 3,
644 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
645 3, 3, 3, 3, 3, 3, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
646 ];
647 assert!(Mobi::new(bytes.to_vec()).is_err());
648 }
649
650 #[test]
651 fn test_backwards_name_offset() {
652 let bytes = [
653 242, 242, 242, 242, 242, 242, 84, 80, 90, 51, 242, 242, 242, 242, 242, 242, 242, 242,
654 242, 242, 242, 242, 242, 250, 242, 118, 178, 242, 242, 242, 62, 131, 126, 126, 126,
655 130, 15, 68, 82, 77, 73, 79, 76, 238, 126, 126, 126, 126, 126, 126, 126, 103, 126, 126,
656 126, 126, 126, 126, 126, 126, 84, 69, 88, 84, 77, 79, 66, 73, 126, 147, 126, 127, 242,
657 136, 41, 126, 0, 1, 0, 0, 0, 0, 0, 0, 4, 126, 84, 69, 88, 84, 82, 242, 242, 84, 80, 90,
658 51, 242, 242, 242, 242, 242, 129, 129, 77, 79, 66, 73, 0, 0, 0, 242, 242, 242, 242,
659 127, 126, 126, 58, 242, 242, 84, 80, 90, 50, 242, 242, 242, 242, 242, 242, 242, 242,
660 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 130, 62, 178, 126, 126, 126, 126,
661 130, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
662 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
663 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
664 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 68, 82, 77, 73, 79,
665 78, 238, 126, 126, 126, 126, 126, 126, 126, 127, 126, 126, 126, 126, 242, 242, 242,
666 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242,
667 242, 242, 242, 242, 242, 242, 242, 242, 178, 130, 126, 126, 126, 126, 126, 126, 126,
668 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 242, 126, 126,
669 126, 126, 126, 126, 126, 126, 84, 69, 88, 84, 82, 69, 65, 68, 82, 126, 126, 126, 242,
670 242, 242, 84, 80, 90, 50, 242, 242, 242, 242, 130, 62, 178, 126, 126, 126, 126, 130,
671 15, 68, 82, 77, 73, 79, 78, 238, 126, 109, 109, 109, 133, 133, 122, 126, 48, 234, 68,
672 82, 77, 73, 79, 78, 238, 65, 68, 126, 126, 126, 126, 242, 136, 126, 1, 0, 1, 0, 242, 0,
673 126, 126, 126, 126, 126, 126, 88, 88, 88, 88, 88, 88, 88, 88, 48, 88, 88, 88, 88, 88,
674 88, 40, 39, 73, 68, 82, 175, 41, 130, 129, 129, 77, 79, 66, 73, 122, 126, 48, 126, 163,
675 163, 44, 163, 163, 163, 163, 163, 40, 39, 40, 172,
676 ];
677 assert!(Mobi::new(bytes.to_vec()).is_err());
678 }
679}