| 652 | } |
| 653 | |
| 654 | fn init(source: DataSource, file_size: u64) -> Result<Self> { |
| 655 | if file_size < GLOBAL_HEADER_SIZE as u64 { |
| 656 | return Err(ParcodeError::Format("File smaller than header".into())); |
| 657 | } |
| 658 | |
| 659 | let header_start = usize::try_from(file_size - GLOBAL_HEADER_SIZE as u64) |
| 660 | .map_err(|_| ParcodeError::Format("File size too large for usize".into()))?; |
| 661 | let header_bytes = source |
| 662 | .get(header_start..) |
| 663 | .ok_or_else(|| ParcodeError::Format("Failed to access global header".into()))?; |
| 664 | |
| 665 | if header_bytes.get(0..4) != Some(&MAGIC_BYTES) { |
| 666 | return Err(ParcodeError::Format("Invalid Magic Bytes".into())); |
| 667 | } |
| 668 | |
| 669 | let version = u16::from_le_bytes( |
| 670 | header_bytes |
| 671 | .get(4..6) |
| 672 | .ok_or_else(|| ParcodeError::Format("Version out of bounds".into()))? |
| 673 | .try_into() |
| 674 | .map_err(|_| ParcodeError::Format("Failed to read version".into()))?, |
| 675 | ); |
| 676 | if version != 4 { |
| 677 | return Err(ParcodeError::Format(format!( |
| 678 | "Unsupported version: {version}. Expected V4." |
| 679 | ))); |
| 680 | } |
| 681 | |
| 682 | let root_offset = u64::from_le_bytes( |
| 683 | header_bytes |
| 684 | .get(6..14) |
| 685 | .ok_or_else(|| ParcodeError::Format("Root offset out of bounds".into()))? |
| 686 | .try_into() |
| 687 | .map_err(|_| ParcodeError::Format("Failed to read root offset".into()))?, |
| 688 | ); |
| 689 | let root_length = u64::from_le_bytes( |
| 690 | header_bytes |
| 691 | .get(14..22) |
| 692 | .ok_or_else(|| ParcodeError::Format("Root length out of bounds".into()))? |
| 693 | .try_into() |
| 694 | .map_err(|_| ParcodeError::Format("Failed to read root length".into()))?, |
| 695 | ); |
| 696 | let checksum = u32::from_le_bytes( |
| 697 | header_bytes |
| 698 | .get(22..26) |
| 699 | .ok_or_else(|| ParcodeError::Format("Checksum out of bounds".into()))? |
| 700 | .try_into() |
| 701 | .map_err(|_| ParcodeError::Format("Failed to read checksum".into()))?, |
| 702 | ); |
| 703 | |
| 704 | let header = GlobalHeader { |
| 705 | magic: MAGIC_BYTES, |
| 706 | version, |
| 707 | root_offset, |
| 708 | root_length, |
| 709 | checksum, |
| 710 | }; |
| 711 | |