gix_packetline_blocking/line/
mod.rs

1// DO NOT EDIT - this is a copy of gix-packetline/src/line/mod.rs. Run `just copy-packetline` to update it.
2
3use bstr::BStr;
4
5use crate::{decode, BandRef, Channel, ErrorRef, PacketLineRef, TextRef, ERR_PREFIX};
6
7impl<'a> PacketLineRef<'a> {
8    /// Return this instance as slice if it's [`Data`][PacketLineRef::Data].
9    pub fn as_slice(&self) -> Option<&'a [u8]> {
10        match self {
11            PacketLineRef::Data(d) => Some(d),
12            PacketLineRef::Flush | PacketLineRef::Delimiter | PacketLineRef::ResponseEnd => None,
13        }
14    }
15    /// Return this instance's [`as_slice()`][PacketLineRef::as_slice()] as [`BStr`].
16    pub fn as_bstr(&self) -> Option<&'a BStr> {
17        self.as_slice().map(Into::into)
18    }
19    /// Interpret this instance's [`as_slice()`][PacketLineRef::as_slice()] as [`ErrorRef`].
20    ///
21    /// This works for any data received in an error [channel][crate::Channel].
22    ///
23    /// Note that this creates an unchecked error using the slice verbatim, which is useful to [serialize it][ErrorRef::write_to()].
24    /// See [`check_error()`][PacketLineRef::check_error()] for a version that assures the error information is in the expected format.
25    pub fn as_error(&self) -> Option<ErrorRef<'a>> {
26        self.as_slice().map(ErrorRef)
27    }
28    /// Check this instance's [`as_slice()`][PacketLineRef::as_slice()] is a valid [`ErrorRef`] and return it.
29    ///
30    /// This works for any data received in an error [channel][crate::Channel].
31    pub fn check_error(&self) -> Option<ErrorRef<'a>> {
32        self.as_slice().and_then(|data| {
33            if data.len() >= ERR_PREFIX.len() && &data[..ERR_PREFIX.len()] == ERR_PREFIX {
34                Some(ErrorRef(&data[ERR_PREFIX.len()..]))
35            } else {
36                None
37            }
38        })
39    }
40    /// Return this instance as text, with the trailing newline truncated if present.
41    pub fn as_text(&self) -> Option<TextRef<'a>> {
42        self.as_slice().map(Into::into)
43    }
44
45    /// Interpret the data in this [`slice`][PacketLineRef::as_slice()] as [`BandRef`] according to the given `kind` of channel.
46    ///
47    /// Note that this is only relevant in a side-band channel.
48    /// See [`decode_band()`][PacketLineRef::decode_band()] in case `kind` is unknown.
49    pub fn as_band(&self, kind: Channel) -> Option<BandRef<'a>> {
50        self.as_slice().map(|d| match kind {
51            Channel::Data => BandRef::Data(d),
52            Channel::Progress => BandRef::Progress(d),
53            Channel::Error => BandRef::Error(d),
54        })
55    }
56
57    /// Decode the band of this [`slice`][PacketLineRef::as_slice()]
58    pub fn decode_band(&self) -> Result<BandRef<'a>, decode::band::Error> {
59        let d = self.as_slice().ok_or(decode::band::Error::NonDataLine)?;
60        Ok(match d[0] {
61            1 => BandRef::Data(&d[1..]),
62            2 => BandRef::Progress(&d[1..]),
63            3 => BandRef::Error(&d[1..]),
64            band => return Err(decode::band::Error::InvalidSideBand { band_id: band }),
65        })
66    }
67}
68
69impl<'a> From<&'a [u8]> for TextRef<'a> {
70    fn from(d: &'a [u8]) -> Self {
71        let d = if d[d.len() - 1] == b'\n' { &d[..d.len() - 1] } else { d };
72        TextRef(d)
73    }
74}
75
76impl<'a> TextRef<'a> {
77    /// Return this instance's data.
78    pub fn as_slice(&self) -> &'a [u8] {
79        self.0
80    }
81    /// Return this instance's data as [`BStr`].
82    pub fn as_bstr(&self) -> &'a BStr {
83        self.0.into()
84    }
85}
86
87#[cfg(all(not(feature = "blocking-io"), feature = "async-io"))]
88mod async_io;
89#[cfg(feature = "blocking-io")]
90mod blocking_io;