1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use libparted_sys::{ped_alignment_align_down, ped_alignment_align_nearest, ped_alignment_align_up,
                    ped_alignment_destroy, ped_alignment_duplicate, ped_alignment_init,
                    ped_alignment_intersect, ped_alignment_is_aligned, ped_alignment_new,
                    PedAlignment};

use std::io;
use std::marker::PhantomData;
use super::{cvt, get_optional, Geometry};

pub struct Alignment<'a> {
    pub(crate) alignment: *mut PedAlignment,
    pub(crate) phantom: PhantomData<&'a PedAlignment>,
}

impl<'a> Alignment<'a> {
    pub fn from_raw(alignment: *mut PedAlignment) -> Alignment<'a> {
        Alignment {
            alignment,
            phantom: PhantomData,
        }
    }

    /// Return an alignment object representing all sectors that are of the form
    /// `offset + X * grain_size`.
    pub fn new(offset: i64, grain_size: i64) -> io::Result<Alignment<'a>> {
        cvt(unsafe { ped_alignment_new(offset, grain_size) }).map(Alignment::from_raw)
    }

    /// Initializes a preallocated piece of memory for an alignment object.
    ///
    /// The object will represent all sectors for which the equation
    /// `S = offset + x * grain_size` holds.
    pub fn init(&mut self, offset: i64, grain_size: i64) -> io::Result<()> {
        cvt(unsafe { ped_alignment_init(self.alignment, offset, grain_size) })?;
        Ok(())
    }

    /// Returns the sector that is closest to `sector`, satifies the `align` constraint, and lies
    /// lies inside `geom`.
    pub fn align_down(&self, geom: &Geometry, sector: i64) -> Option<u64> {
        match unsafe { ped_alignment_align_down(self.alignment, geom.geometry, sector) } {
            -1 => None,
            sector => Some(sector as u64),
        }
    }

    /// Returns the sector that is closest to `sector`, satisfies the `align` constraint, and
    /// lies inside of `geom`.
    pub fn align_nearest(&self, geom: &Geometry, sector: i64) -> Option<u64> {
        match unsafe { ped_alignment_align_nearest(self.alignment, geom.geometry, sector) } {
            -1 => None,
            sector => Some(sector as u64),
        }
    }

    /// Returns the sector that is closest to `sector`, satifies the `align` constraint, and lies
    /// lies inside `geom`.
    pub fn align_up(&self, geom: &Geometry, sector: i64) -> Option<u64> {
        match unsafe { ped_alignment_align_up(self.alignment, geom.geometry, sector) } {
            -1 => None,
            sector => Some(sector as u64),
        }
    }

    /// Clones and returns a duplicate of the alignment, if possible.
    pub fn duplicate<'b>(&self) -> io::Result<Alignment<'b>> {
        cvt(unsafe { ped_alignment_duplicate(self.alignment) }).map(|alignment| Alignment {
            alignment,
            phantom: PhantomData,
        })
    }

    pub fn grain_size(&self) -> i64 {
        unsafe { (*self.alignment).grain_size }
    }

    /// Returns a new **Alignment** object if an intersection can between
    /// itself and a given `other` **Alignment**.
    pub fn intersect(&self, other: &Alignment) -> Option<Alignment<'a>> {
        get_optional(unsafe { ped_alignment_intersect(self.alignment, other.alignment) })
            .map(Alignment::from_raw)
    }

    /// Returns the sector that is closest to `sector`, satifies the `align` constraint, and lies
    /// lies inside `geom`.
    pub fn is_aligned(&self, geom: &Geometry, sector: i64) -> bool {
        unsafe { ped_alignment_is_aligned(self.alignment, geom.geometry, sector) == 1 }
    }

    pub fn offset(&self) -> i64 {
        unsafe { (*self.alignment).offset }
    }
}
impl<'a> Drop for Alignment<'a> {
    fn drop(&mut self) {
        unsafe { ped_alignment_destroy(self.alignment) }
    }
}