anvilsign in

collin/anvil

main / vendor / gitserver-core / src / pktline.rs
1//! pkt-line encoding as defined by Git protocol.
2//! Format: 4-hex-digit length prefix (includes the 4 bytes) + content.
3//! Flush packet: "0000"
4
5/// Encode a single pkt-line.
6pub fn encode(data: &[u8]) -> Vec<u8> {
7 let len = data.len() + 4;
8 let mut buf = format!("{len:04x}").into_bytes();
9 buf.extend_from_slice(data);
10 buf
11}
12
13/// Encode a flush packet.
14pub fn flush() -> &'static [u8] {
15 b"0000"
16}
17
18/// Encode a comment line (e.g. "# service=git-upload-pack\n").
19pub fn encode_comment(comment: &str) -> Vec<u8> {
20 encode(format!("# {comment}\n").as_bytes())
21}
22
23#[cfg(test)]
24mod tests {
25 use super::*;
26
27 #[test]
28 fn encode_simple_line() {
29 let encoded = encode(b"hello\n");
30 assert_eq!(&encoded, b"000ahello\n");
31 }
32
33 #[test]
34 fn encode_empty_content() {
35 let encoded = encode(b"");
36 assert_eq!(&encoded, b"0004");
37 }
38
39 #[test]
40 fn encode_comment_line() {
41 let encoded = encode_comment("service=git-upload-pack");
42 assert_eq!(&encoded, b"001e# service=git-upload-pack\n");
43 }
44
45 #[test]
46 fn flush_packet() {
47 assert_eq!(flush(), b"0000");
48 }
49
50 #[test]
51 fn encode_ref_line() {
52 let hash = "0000000000000000000000000000000000000000";
53 let line = format!("{hash} refs/heads/main\n");
54 let encoded = encode(line.as_bytes());
55 // 4 (prefix) + 40 (hash) + 1 (space) + 15 (refs/heads/main) + 1 (\n) = 61 = 0x3d
56 assert_eq!(&encoded[..4], b"003d");
57 }
58}