icsneoc2 0.1002002.0-rc.4

High-level Rust interface for Intrepid Control Systems vehicle network adapters
Documentation
//! Disk details and formatting for on-device storage.
//!
//! Intrepid devices with SD card or flash storage expose disk management
//! through [`DiskDetails`]. Obtain a handle via
//! [`Device::disk_details`](crate::Device::disk_details), inspect or modify
//! partition flags/layout, then call
//! [`Device::format_disk`](crate::Device::format_disk) to format.
//!
//! [`DiskSize`] describes a single partition's capacity in sectors and
//! bytes per sector.

use std::ptr::NonNull;

use crate::enums::DiskFormatFlags;
use crate::error::Result;
use crate::functions::check;
use crate::sys;

/// Size information for a single disk partition.
///
/// Total capacity in bytes = `sectors * bytes_per_sector`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DiskSize {
    /// Number of addressable sectors on this partition.
    pub sectors: u64,
    /// Size of each sector in bytes (commonly 512).
    pub bytes_per_sector: u64,
}

/// Owned handle to disk detail information.
///
/// Obtained via [`Device::disk_details`](crate::Device::disk_details).
/// Freed automatically on drop via `icsneoc2_disk_details_free`.
///
/// Provides read/write access to the disk layout, partition flags, and
/// format configuration before passing the handle to
/// [`Device::format_disk`](crate::Device::format_disk).
pub struct DiskDetails {
    ptr: NonNull<sys::icsneoc2_disk_details_t>,
}

unsafe impl Send for DiskDetails {}

impl Drop for DiskDetails {
    fn drop(&mut self) {
        unsafe { sys::icsneoc2_disk_details_free(self.ptr.as_ptr()) };
    }
}

impl DiskDetails {
    pub(crate) fn new(ptr: NonNull<sys::icsneoc2_disk_details_t>) -> Self {
        Self { ptr }
    }

    pub(crate) fn as_ptr(&self) -> *mut sys::icsneoc2_disk_details_t {
        self.ptr.as_ptr()
    }

    /// Returns the number of disk partitions described by this handle.
    pub fn count(&self) -> Result<usize> {
        let mut value: usize = 0;
        check(unsafe { sys::icsneoc2_disk_details_count_get(self.ptr.as_ptr(), &raw mut value) })?;
        Ok(value)
    }

    /// Returns the disk layout (e.g. Spanned, RAID0).
    pub fn layout(&self) -> Result<sys::DiskLayout> {
        let mut raw: sys::icsneoc2_disk_layout_t = 0;
        check(unsafe { sys::icsneoc2_disk_details_layout_get(self.ptr.as_ptr(), &raw mut raw) })?;
        Ok(sys::DiskLayout::try_from(raw)?)
    }

    /// Sets the disk layout (e.g. Spanned, RAID0).
    pub fn set_layout(&self, layout: sys::DiskLayout) -> Result<()> {
        check(unsafe {
            sys::icsneoc2_disk_details_layout_set(
                self.ptr.as_ptr(),
                sys::icsneoc2_disk_layout_t::from(layout),
            )
        })
    }

    /// Returns the format flags for a partition at the given zero-based `index`.
    ///
    /// Flags indicate whether the partition is present, initialized, and/or
    /// formatted. See [`DiskFormatFlags`].
    pub fn flags(&self, index: usize) -> Result<DiskFormatFlags> {
        let mut value: sys::icsneoc2_disk_format_flags_t = 0;
        check(unsafe {
            sys::icsneoc2_disk_details_flags_get(self.ptr.as_ptr(), index, &raw mut value)
        })?;
        Ok(DiskFormatFlags::from(value))
    }

    /// Sets the format flags for a partition at the given zero-based `index`.
    ///
    /// Set [`DiskFormatFlags::FORMATTED`] on partitions you want to format.
    pub fn set_flags(&self, index: usize, flags: DiskFormatFlags) -> Result<()> {
        check(unsafe {
            sys::icsneoc2_disk_details_flags_set(
                self.ptr.as_ptr(),
                index,
                sys::icsneoc2_disk_format_flags_t::from(flags),
            )
        })
    }

    /// Returns the size of a partition at the given zero-based `index`.
    pub fn size(&self, index: usize) -> Result<DiskSize> {
        let mut sectors: u64 = 0;
        let mut bytes_per_sector: u64 = 0;
        check(unsafe {
            sys::icsneoc2_disk_details_size_get(
                self.ptr.as_ptr(),
                index,
                &raw mut sectors,
                &raw mut bytes_per_sector,
            )
        })?;
        Ok(DiskSize {
            sectors,
            bytes_per_sector,
        })
    }

    /// Returns `true` if a full (slow) format is configured rather than a quick format.
    pub fn is_full_format(&self) -> Result<bool> {
        let mut value = false;
        check(unsafe {
            sys::icsneoc2_disk_details_full_format_get(self.ptr.as_ptr(), &raw mut value)
        })?;
        Ok(value)
    }

    /// Configures full format (`true`) or quick format (`false`).
    ///
    /// A full format writes zeros to every sector and is significantly
    /// slower than a quick format.
    pub fn set_full_format(&self, value: bool) -> Result<()> {
        check(unsafe { sys::icsneoc2_disk_details_full_format_set(self.ptr.as_ptr(), value) })
    }
}