#![no_std]
#![allow(async_fn_in_trait)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
pub mod error;
pub mod geometry;
pub mod gpt;
pub mod hybrid;
pub mod mbr;
pub mod scheme;
#[cfg(feature = "sync")]
#[path = ""]
pub mod sync {
pub use hadris_io::Result as IoResult;
pub use hadris_io::sync::{Parsable, Read, ReadExt, Seek, Writable, Write};
pub use hadris_io::{Error, ErrorKind, SeekFrom};
macro_rules! io_transform {
($($item:tt)*) => { hadris_macros::strip_async!{ $($item)* } };
}
macro_rules! sync_only {
($($item:tt)*) => { $($item)* };
}
macro_rules! async_only {
($($item:tt)*) => {};
}
#[path = "."]
mod __inner {
pub mod gpt_io;
pub mod mbr_io;
pub mod scheme_io;
}
pub use __inner::*;
}
#[cfg(feature = "async")]
#[path = ""]
pub mod r#async {
pub use hadris_io::Result as IoResult;
pub use hadris_io::r#async::{Parsable, Read, ReadExt, Seek, Writable, Write};
pub use hadris_io::{Error, ErrorKind, SeekFrom};
macro_rules! io_transform {
($($item:tt)*) => { $($item)* };
}
macro_rules! sync_only {
($($item:tt)*) => {};
}
macro_rules! async_only {
($($item:tt)*) => { $($item)* };
}
#[path = "."]
mod __inner {
pub mod gpt_io;
pub mod mbr_io;
pub mod scheme_io;
}
pub use __inner::*;
}
#[cfg(feature = "sync")]
pub use sync::*;
pub use error::{PartitionError, Result};
pub use geometry::{DiskGeometry, validate_partition_alignment};
pub use gpt::{GptHeader, GptPartitionEntry, Guid};
pub use mbr::{Chs, MasterBootRecord, MbrPartition, MbrPartitionTable, MbrPartitionType};
pub use scheme::{PartitionInfo, PartitionSchemeType, PartitionType};
#[cfg(feature = "alloc")]
pub use scheme::{DiskPartitionScheme, GptDisk};
pub trait PartitionInfoTrait {
fn start_lba(&self) -> u64;
fn size_sectors(&self) -> u64;
fn end_lba(&self) -> u64 {
let size = self.size_sectors();
if size == 0 {
self.start_lba()
} else {
self.start_lba() + size - 1
}
}
fn size_bytes(&self) -> u64 {
self.size_sectors() * 512
}
fn size_bytes_with_sector_size(&self, sector_size: u32) -> u64 {
self.size_sectors() * sector_size as u64
}
}
impl PartitionInfoTrait for MbrPartition {
fn start_lba(&self) -> u64 {
self.start_lba as u64
}
fn size_sectors(&self) -> u64 {
self.sector_count as u64
}
}
impl PartitionInfoTrait for GptPartitionEntry {
fn start_lba(&self) -> u64 {
self.first_lba
}
fn size_sectors(&self) -> u64 {
if self.is_unused() || self.last_lba < self.first_lba {
0
} else {
self.last_lba - self.first_lba + 1
}
}
fn end_lba(&self) -> u64 {
self.last_lba
}
}
impl PartitionInfoTrait for PartitionInfo {
fn start_lba(&self) -> u64 {
self.start_lba
}
fn size_sectors(&self) -> u64 {
self.size_sectors
}
fn end_lba(&self) -> u64 {
self.end_lba
}
}
pub trait PartitionTableRead {
type Partition: PartitionInfoTrait;
fn partition_count(&self) -> usize;
fn partition(&self, index: usize) -> Option<&Self::Partition>;
}
impl PartitionTableRead for MbrPartitionTable {
type Partition = MbrPartition;
fn partition_count(&self) -> usize {
self.count()
}
fn partition(&self, index: usize) -> Option<&Self::Partition> {
if index < 4 && !self.partitions[index].is_empty() {
Some(&self.partitions[index])
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mbr_partition_trait() {
let partition = MbrPartition::new(MbrPartitionType::Fat32, 2048, 204800);
assert_eq!(partition.start_lba(), 2048);
assert_eq!(partition.size_sectors(), 204800);
assert_eq!(partition.end_lba(), 2048 + 204800 - 1);
assert_eq!(partition.size_bytes(), 204800 * 512);
}
#[test]
fn test_gpt_partition_trait() {
let partition = GptPartitionEntry::new(Guid::EFI_SYSTEM, Guid::UNUSED, 2048, 206847);
assert_eq!(partition.start_lba(), 2048);
assert_eq!(partition.size_sectors(), 204800);
assert_eq!(partition.end_lba(), 206847);
}
#[test]
fn test_mbr_table_read_trait() {
let mut table = MbrPartitionTable::new();
table[0] = MbrPartition::new(MbrPartitionType::Fat32, 2048, 204800);
table[1] = MbrPartition::new(MbrPartitionType::LinuxNative, 206848, 1000000);
assert_eq!(table.partition_count(), 2);
assert!(table.partition(0).is_some());
assert!(table.partition(1).is_some());
assert!(table.partition(2).is_none());
assert!(table.partition(3).is_none());
}
#[test]
fn test_struct_sizes() {
assert_eq!(core::mem::size_of::<MbrPartition>(), 16);
assert_eq!(core::mem::size_of::<MbrPartitionTable>(), 64);
assert_eq!(core::mem::size_of::<MasterBootRecord>(), 512);
assert!(core::mem::size_of::<GptHeader>() >= 92);
assert_eq!(core::mem::size_of::<GptPartitionEntry>(), 128);
}
}