Skip to content

Commit 1a986fb

Browse files
committed
[git-packetline] prepare 'packetline' and 'encode' for async
1 parent ec70cb3 commit 1a986fb

File tree

3 files changed

+114
-90
lines changed

3 files changed

+114
-90
lines changed

git-packetline/src/encode.rs

Lines changed: 64 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
use crate::{Channel, DELIMITER_LINE, ERR_PREFIX, FLUSH_LINE, MAX_DATA_LEN, RESPONSE_END_LINE};
1+
use crate::MAX_DATA_LEN;
22
use quick_error::quick_error;
3-
use std::io;
43

54
quick_error! {
65
/// The error returned by most functions in the [`encode`][crate::encode] module
76
#[derive(Debug)]
87
#[allow(missing_docs)]
98
pub enum Error {
10-
Io(err: io::Error) {
9+
Io(err: std::io::Error) {
1110
display("An error occurred while writing")
1211
from()
1312
source(err)
@@ -21,72 +20,81 @@ quick_error! {
2120
}
2221
}
2322

24-
/// Write a response-end message to `out`.
25-
pub fn response_end_to_write(mut out: impl io::Write) -> io::Result<usize> {
26-
out.write_all(RESPONSE_END_LINE).map(|_| 4)
27-
}
28-
29-
/// Write a delim message to `out`.
30-
pub fn delim_to_write(mut out: impl io::Write) -> io::Result<usize> {
31-
out.write_all(DELIMITER_LINE).map(|_| 4)
32-
}
23+
#[cfg(feature = "blocking-io")]
24+
mod blocking_io {
25+
use super::u16_to_hex;
26+
use crate::{encode::Error, Channel, DELIMITER_LINE, ERR_PREFIX, FLUSH_LINE, MAX_DATA_LEN, RESPONSE_END_LINE};
27+
use std::io;
3328

34-
/// Write a flush message to `out`.
35-
pub fn flush_to_write(mut out: impl io::Write) -> io::Result<usize> {
36-
out.write_all(FLUSH_LINE).map(|_| 4)
37-
}
29+
/// Write a response-end message to `out`.
30+
pub fn response_end_to_write(mut out: impl io::Write) -> io::Result<usize> {
31+
out.write_all(RESPONSE_END_LINE).map(|_| 4)
32+
}
3833

39-
/// Write an error `message` to `out`.
40-
pub fn error_to_write(message: &[u8], out: impl io::Write) -> Result<usize, Error> {
41-
prefixed_data_to_write(ERR_PREFIX, message, out)
42-
}
34+
/// Write a delim message to `out`.
35+
pub fn delim_to_write(mut out: impl io::Write) -> io::Result<usize> {
36+
out.write_all(DELIMITER_LINE).map(|_| 4)
37+
}
4338

44-
/// Write `data` of `kind` to `out` using side-band encoding.
45-
pub fn band_to_write(kind: Channel, data: &[u8], out: impl io::Write) -> Result<usize, Error> {
46-
prefixed_data_to_write(&[kind as u8], data, out)
47-
}
39+
/// Write a flush message to `out`.
40+
pub fn flush_to_write(mut out: impl io::Write) -> io::Result<usize> {
41+
out.write_all(FLUSH_LINE).map(|_| 4)
42+
}
4843

49-
/// Write a `data` message to `out`.
50-
pub fn data_to_write(data: &[u8], out: impl io::Write) -> Result<usize, Error> {
51-
prefixed_data_to_write(&[], data, out)
52-
}
44+
/// Write an error `message` to `out`.
45+
pub fn error_to_write(message: &[u8], out: impl io::Write) -> Result<usize, Error> {
46+
prefixed_data_to_write(ERR_PREFIX, message, out)
47+
}
5348

54-
/// Write a `text` message to `out`, which is assured to end in a newline.
55-
pub fn text_to_write(text: &[u8], out: impl io::Write) -> Result<usize, Error> {
56-
prefixed_and_suffixed_data_to_write(&[], text, &[b'\n'], out)
57-
}
49+
/// Write `data` of `kind` to `out` using side-band encoding.
50+
pub fn band_to_write(kind: Channel, data: &[u8], out: impl io::Write) -> Result<usize, Error> {
51+
prefixed_data_to_write(&[kind as u8], data, out)
52+
}
5853

59-
fn prefixed_data_to_write(prefix: &[u8], data: &[u8], out: impl io::Write) -> Result<usize, Error> {
60-
prefixed_and_suffixed_data_to_write(prefix, data, &[], out)
61-
}
54+
/// Write a `data` message to `out`.
55+
pub fn data_to_write(data: &[u8], out: impl io::Write) -> Result<usize, Error> {
56+
prefixed_data_to_write(&[], data, out)
57+
}
6258

63-
fn prefixed_and_suffixed_data_to_write(
64-
prefix: &[u8],
65-
data: &[u8],
66-
suffix: &[u8],
67-
mut out: impl io::Write,
68-
) -> Result<usize, Error> {
69-
let data_len = prefix.len() + data.len() + suffix.len();
70-
if data_len > MAX_DATA_LEN {
71-
return Err(Error::DataLengthLimitExceeded(data_len));
59+
/// Write a `text` message to `out`, which is assured to end in a newline.
60+
pub fn text_to_write(text: &[u8], out: impl io::Write) -> Result<usize, Error> {
61+
prefixed_and_suffixed_data_to_write(&[], text, &[b'\n'], out)
7262
}
73-
if data.is_empty() {
74-
return Err(Error::DataIsEmpty);
63+
64+
fn prefixed_data_to_write(prefix: &[u8], data: &[u8], out: impl io::Write) -> Result<usize, Error> {
65+
prefixed_and_suffixed_data_to_write(prefix, data, &[], out)
7566
}
7667

77-
let data_len = data_len + 4;
78-
let buf = u16_to_hex(data_len as u16);
68+
fn prefixed_and_suffixed_data_to_write(
69+
prefix: &[u8],
70+
data: &[u8],
71+
suffix: &[u8],
72+
mut out: impl io::Write,
73+
) -> Result<usize, Error> {
74+
let data_len = prefix.len() + data.len() + suffix.len();
75+
if data_len > MAX_DATA_LEN {
76+
return Err(Error::DataLengthLimitExceeded(data_len));
77+
}
78+
if data.is_empty() {
79+
return Err(Error::DataIsEmpty);
80+
}
7981

80-
out.write_all(&buf)?;
81-
if !prefix.is_empty() {
82-
out.write_all(prefix)?;
83-
}
84-
out.write_all(data)?;
85-
if !suffix.is_empty() {
86-
out.write_all(suffix)?;
82+
let data_len = data_len + 4;
83+
let buf = u16_to_hex(data_len as u16);
84+
85+
out.write_all(&buf)?;
86+
if !prefix.is_empty() {
87+
out.write_all(prefix)?;
88+
}
89+
out.write_all(data)?;
90+
if !suffix.is_empty() {
91+
out.write_all(suffix)?;
92+
}
93+
Ok(data_len)
8794
}
88-
Ok(data_len)
8995
}
96+
#[cfg(feature = "blocking-io")]
97+
pub use blocking_io::*;
9098

9199
pub(crate) fn u16_to_hex(value: u16) -> [u8; 4] {
92100
let mut buf = [0u8; 4];

git-packetline/src/immutable.rs

Lines changed: 48 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use crate::{encode, Channel, ERR_PREFIX};
1+
use crate::{Channel, ERR_PREFIX};
22
use bstr::BStr;
3-
use std::io;
43

54
/// A borrowed packet line as it refers to a slice of data by reference.
65
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
@@ -17,16 +16,6 @@ pub enum PacketLine<'a> {
1716
}
1817

1918
impl<'a> PacketLine<'a> {
20-
/// Serialize this instance to `out` in git `packetline` format, returning the amount of bytes written to `out`.
21-
pub fn to_write(&self, out: impl io::Write) -> Result<usize, encode::Error> {
22-
match self {
23-
PacketLine::Data(d) => encode::data_to_write(d, out),
24-
PacketLine::Flush => encode::flush_to_write(out).map_err(Into::into),
25-
PacketLine::Delimiter => encode::delim_to_write(out).map_err(Into::into),
26-
PacketLine::ResponseEnd => encode::response_end_to_write(out).map_err(Into::into),
27-
}
28-
}
29-
3019
/// Return this instance as slice if it's [`Data`][PacketLine::Data].
3120
pub fn as_slice(&self) -> Option<&[u8]> {
3221
match self {
@@ -108,15 +97,6 @@ quick_error! {
10897
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
10998
pub struct Error<'a>(pub &'a [u8]);
11099

111-
impl<'a> Error<'a> {
112-
/// Serialize this line as error to `out`.
113-
///
114-
/// This includes a marker to allow decoding it outside of a side-band channel, returning the amount of bytes written.
115-
pub fn to_write(&self, out: impl io::Write) -> Result<usize, encode::Error> {
116-
encode::error_to_write(self.0, out)
117-
}
118-
}
119-
120100
/// A packet line representing text, which may include a trailing newline.
121101
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
122102
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
@@ -138,10 +118,6 @@ impl<'a> Text<'a> {
138118
pub fn as_bstr(&self) -> &BStr {
139119
self.0.into()
140120
}
141-
/// Serialize this instance to `out`, appending a newline if there is none, returning the amount of bytes written.
142-
pub fn to_write(&self, out: impl io::Write) -> Result<usize, encode::Error> {
143-
encode::text_to_write(self.0, out)
144-
}
145121
}
146122

147123
/// A band in a side-band channel.
@@ -156,15 +132,53 @@ pub enum Band<'a> {
156132
Error(&'a [u8]),
157133
}
158134

159-
impl<'a> Band<'a> {
160-
/// Serialize this instance to `out`, returning the amount of bytes written.
161-
///
162-
/// The data written to `out` can be decoded with [`Borrowed::decode_band()]`.
163-
pub fn to_write(&self, out: impl io::Write) -> Result<usize, encode::Error> {
164-
match self {
165-
Band::Data(d) => encode::band_to_write(Channel::Data, d, out),
166-
Band::Progress(d) => encode::band_to_write(Channel::Progress, d, out),
167-
Band::Error(d) => encode::band_to_write(Channel::Error, d, out),
135+
#[cfg(feature = "blocking-io")]
136+
mod blocking_io {
137+
use crate::{
138+
encode,
139+
immutable::{Band, Error, Text},
140+
Channel, PacketLine,
141+
};
142+
use std::io;
143+
144+
impl<'a> Band<'a> {
145+
/// Serialize this instance to `out`, returning the amount of bytes written.
146+
///
147+
/// The data written to `out` can be decoded with [`Borrowed::decode_band()]`.
148+
pub fn to_write(&self, out: impl io::Write) -> Result<usize, encode::Error> {
149+
match self {
150+
Band::Data(d) => encode::band_to_write(Channel::Data, d, out),
151+
Band::Progress(d) => encode::band_to_write(Channel::Progress, d, out),
152+
Band::Error(d) => encode::band_to_write(Channel::Error, d, out),
153+
}
154+
}
155+
}
156+
157+
impl<'a> Text<'a> {
158+
/// Serialize this instance to `out`, appending a newline if there is none, returning the amount of bytes written.
159+
pub fn to_write(&self, out: impl io::Write) -> Result<usize, encode::Error> {
160+
encode::text_to_write(self.0, out)
161+
}
162+
}
163+
164+
impl<'a> Error<'a> {
165+
/// Serialize this line as error to `out`.
166+
///
167+
/// This includes a marker to allow decoding it outside of a side-band channel, returning the amount of bytes written.
168+
pub fn to_write(&self, out: impl io::Write) -> Result<usize, encode::Error> {
169+
encode::error_to_write(self.0, out)
170+
}
171+
}
172+
173+
impl<'a> PacketLine<'a> {
174+
/// Serialize this instance to `out` in git `packetline` format, returning the amount of bytes written to `out`.
175+
pub fn to_write(&self, out: impl io::Write) -> Result<usize, encode::Error> {
176+
match self {
177+
PacketLine::Data(d) => encode::data_to_write(d, out),
178+
PacketLine::Flush => encode::flush_to_write(out).map_err(Into::into),
179+
PacketLine::Delimiter => encode::delim_to_write(out).map_err(Into::into),
180+
PacketLine::ResponseEnd => encode::response_end_to_write(out).map_err(Into::into),
181+
}
168182
}
169183
}
170184
}

git-packetline/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ pub mod read;
3434
pub use read::StreamingPeekableIter;
3535

3636
///
37+
#[cfg(any(feature = "async-io", feature = "blocking-io"))]
3738
pub mod write;
39+
#[cfg(any(feature = "async-io", feature = "blocking-io"))]
3840
#[doc(inline)]
3941
pub use write::Writer;
4042

0 commit comments

Comments
 (0)