summaryrefslogtreecommitdiff
path: root/bch_bindgen/src/lib.rs
blob: d903735e29f5703183645cc03f01ac1ae0c14f35 (plain)
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
pub mod bcachefs;
pub mod btree;
pub mod bkey;
pub mod errcode;
pub mod keyutils;
pub mod sb_io;
pub mod fs;
pub mod opts;
pub use paste::paste;

pub mod c {
    pub use crate::bcachefs::*;
}

use c::bpos as Bpos;

pub const fn spos(inode: u64, offset: u64, snapshot: u32) -> Bpos {
    Bpos { inode, offset, snapshot }
}

pub const fn pos(inode: u64, offset: u64) -> Bpos {
    spos(inode, offset, 0)
}

pub const POS_MIN:  Bpos = spos(0, 0, 0);
pub const POS_MAX:  Bpos = spos(u64::MAX, u64::MAX, 0);
pub const SPOS_MAX: Bpos = spos(u64::MAX, u64::MAX, u32::MAX);

use std::cmp::Ordering;

impl PartialEq for Bpos {
    fn eq(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Equal
    }
}

impl Eq for Bpos {}

impl PartialOrd for Bpos {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Bpos {
    fn cmp(&self, other: &Self) -> Ordering {
        let l_inode     = self.inode;
        let r_inode     = other.inode;
        let l_offset    = self.offset;
        let r_offset    = other.offset;
        let l_snapshot  = self.snapshot;
        let r_snapshot  = other.snapshot;

        l_inode.cmp(&r_inode)
            .then(l_offset.cmp(&r_offset))
            .then(l_snapshot.cmp(&r_snapshot))
    }
}

use std::ffi::CStr;
use std::fmt;

impl fmt::Display for c::btree_id {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = unsafe { CStr::from_ptr(c::bch2_btree_id_str(*self)) };
        let s = s.to_str().unwrap();
        write!(f, "{}", s)
    }
}

use std::str::FromStr;
use std::ffi::CString;
use std::{path::Path,os::unix::ffi::OsStrExt};

pub fn path_to_cstr<P: AsRef<Path>>(p: P) -> CString {
    CString::new(p.as_ref().as_os_str().as_bytes()).unwrap()
}

use std::error::Error;

#[derive(Debug)]
pub struct InvalidBtreeId;

impl fmt::Display for InvalidBtreeId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "invalid btree id")
    }
}

impl Error for InvalidBtreeId {
}

impl FromStr for c::btree_id {
    type Err = InvalidBtreeId;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let s = CString::new(s).unwrap();
        let p = s.as_ptr();

        let v = unsafe {c::match_string(c::__bch2_btree_ids[..].as_ptr(), (-(1 as isize)) as usize, p)};
        if v >= 0 {
            Ok(unsafe { std::mem::transmute(v) })
        } else {
            Err(InvalidBtreeId)
        }
    }
}

impl c::printbuf {
    fn new() -> c::printbuf {
        let mut buf: c::printbuf = Default::default();

        buf.set_heap_allocated(true);
        buf
    }
}

impl Drop for c::printbuf {
    fn drop(&mut self) {
        unsafe { c::bch2_printbuf_exit(self) }
    }             
}

impl fmt::Display for Bpos {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buf = c::printbuf::new();

        unsafe { c::bch2_bpos_to_text(&mut buf, *self) };
 
        let s = unsafe { CStr::from_ptr(buf.buf) };
        let s = s.to_str().unwrap();
        write!(f, "{}", s)
    }
}

impl FromStr for c::bpos {
    type Err = InvalidBtreeId;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s == "POS_MIN" {
            return Ok(POS_MIN);
        }

        if s == "POS_MAX" {
            return Ok(POS_MAX);
        }

        if s == "SPOS_MAX" {
            return Ok(SPOS_MAX);
        }

        let mut fields = s.split(':');
        let ino_str = fields.next().ok_or(InvalidBtreeId)?;
        let off_str = fields.next().ok_or(InvalidBtreeId)?;
        let snp_str = fields.next();

        let ino: u64    = ino_str.parse().map_err(|_| InvalidBtreeId)?;
        let off: u64    = off_str.parse().map_err(|_| InvalidBtreeId)?;
        let snp: u32    = snp_str.map(|s| s.parse().ok()).flatten().unwrap_or(0);

        Ok(c::bpos { inode: ino, offset: off, snapshot: snp })
    }
}

pub fn printbuf_to_formatter<F>(f: &mut fmt::Formatter<'_>, func: F) -> fmt::Result
    where F: Fn(*mut c::printbuf) {
    let mut buf = c::printbuf::new();

    func(&mut buf);

    let s = unsafe { CStr::from_ptr(buf.buf) };
    f.write_str(&s.to_string_lossy())
}