summaryrefslogtreecommitdiff
path: root/src/util.rs
blob: 2ad8c0082cabb0d731ca7148a0ee7ffe05e17a3a (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
use std::{
    fmt,
    os::unix::io::{IntoRawFd, RawFd},
};

use nix::unistd::close;
use quick_error::quick_error;

quick_error! {
    #[derive(Debug)]
    pub enum FuseError {
        Io(err: std::io::Error) { from() }
        ProtocolInit { display("fuse handshake failed (ancient kernel?)") }
        Truncated { display("fuse request truncated") }
        BadOpcode { display("unknown fuse operation") }
        BadLength { display("bad length in fuse request") }
        ShortWrite { display("fuse reply was trimmed on write()") }
    }
}

pub type FuseResult<T> = Result<T, FuseError>;

pub struct DumbFd(pub RawFd);

pub struct OutputChain<'a> {
    segments: &'a [&'a [u8]],
    then: Option<&'a OutputChain<'a>>,
}

pub struct OutputChainIter<'a>(Option<&'a OutputChain<'a>>);

impl IntoRawFd for DumbFd {
    fn into_raw_fd(self) -> RawFd {
        let fd = self.0;
        std::mem::forget(self);
        fd
    }
}

impl Drop for DumbFd {
    fn drop(&mut self) {
        let _ = close(self.0);
    }
}

impl<'a> OutputChain<'a> {
    pub fn empty() -> Self {
        OutputChain {
            segments: &[],
            then: None,
        }
    }

    pub fn tail(segments: &'a [&'a [u8]]) -> Self {
        OutputChain {
            segments,
            then: None,
        }
    }

    pub fn preceded(&'a self, segments: &'a [&'a [u8]]) -> Self {
        OutputChain {
            segments,
            then: Some(self),
        }
    }

    pub fn iter(&self) -> OutputChainIter<'_> {
        OutputChainIter(Some(self))
    }
}

impl<'a> Iterator for OutputChainIter<'a> {
    type Item = &'a [&'a [u8]];

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.0.and_then(|chain| chain.then);
        std::mem::replace(&mut self.0, next).map(|chain| chain.segments)
    }
}

pub fn display_or<'a, T: fmt::Display + 'a>(
    maybe: Option<T>,
    default: &'a str,
) -> impl fmt::Display + 'a {
    struct Params<'a, T: fmt::Display>(Option<T>, &'a str);

    impl<T: fmt::Display> fmt::Display for Params<'_, T> {
        fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
            let Params(maybe, placeholder) = &self;
            if let Some(t) = maybe {
                write!(fmt, "{}", t)
            } else {
                fmt.write_str(placeholder)
            }
        }
    }

    Params(maybe, default)
}