vortex_protocol/tlv/
mod.rs

1/*
2 *     Copyright 2025 The Dragonfly Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17pub mod cache_piece_content;
18pub mod close;
19pub mod download_cache_piece;
20pub mod download_persistent_cache_piece;
21pub mod download_piece;
22pub mod error;
23pub mod persistent_cache_piece_content;
24pub mod piece_content;
25
26/// Tag Definitions
27#[repr(u8)]
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum Tag {
30    /// Download the content of a piece from a peer. It is composed of `{Task ID}{Piece ID}`,
31    /// where the Task ID is a SHA-256 value and the Piece ID is a number.
32    DownloadPiece = 0,
33
34    /// The content of a piece, with a maximum size of 4 GiB per piece.
35    PieceContent = 1,
36
37    /// Download the content of a persistent cache piece from a peer. It is composed of `{Task ID}{Piece ID}`,
38    /// where the Task ID is a SHA-256 value and the Piece ID is a number.
39    DownloadPersistentCachePiece = 2,
40
41    /// The content of a persistent cache piece, with a maximum size of 4 GiB per piece.
42    PersistentCachePieceContent = 3,
43
44    /// Download the content of a cache piece from a peer. It is composed of `{Task ID}{Piece ID}`,
45    /// where the Task ID is a SHA-256 value and the Piece ID is a number.
46    DownloadCachePiece = 4,
47
48    /// The content of a cache piece, with a maximum size of 4 GiB per piece.
49    CachePieceContent = 5,
50
51    /// Reserved for future use, for tags 6-254.
52    Reserved(u8),
53
54    /// Close the connection. If server or client receives this tag, it will close the connection.
55    Close = 254,
56
57    /// Error message.
58    Error = 255,
59}
60
61/// Implement TryFrom<u8> for Tag.
62impl From<u8> for Tag {
63    /// Converts a u8 to a Tag enum.
64    fn from(value: u8) -> Self {
65        match value {
66            0 => Tag::DownloadPiece,
67            1 => Tag::PieceContent,
68            2 => Tag::DownloadPersistentCachePiece,
69            3 => Tag::PersistentCachePieceContent,
70            4 => Tag::DownloadCachePiece,
71            5 => Tag::CachePieceContent,
72            6..=253 => Tag::Reserved(value),
73            254 => Tag::Close,
74            255 => Tag::Error,
75        }
76    }
77}
78
79/// Implement From<Tag> for u8.
80impl From<Tag> for u8 {
81    /// Converts a Tag enum to a u8.
82    fn from(tag: Tag) -> Self {
83        match tag {
84            Tag::DownloadPiece => 0,
85            Tag::PieceContent => 1,
86            Tag::DownloadPersistentCachePiece => 2,
87            Tag::PersistentCachePieceContent => 3,
88            Tag::DownloadCachePiece => 4,
89            Tag::CachePieceContent => 5,
90            Tag::Reserved(value) => value,
91            Tag::Close => 254,
92            Tag::Error => 255,
93        }
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100
101    #[test]
102    fn test_try_from_u8() {
103        assert_eq!(Tag::from(0), Tag::DownloadPiece);
104        assert_eq!(Tag::from(1), Tag::PieceContent);
105        assert_eq!(Tag::from(2), Tag::DownloadPersistentCachePiece);
106        assert_eq!(Tag::from(3), Tag::PersistentCachePieceContent);
107        assert_eq!(Tag::from(4), Tag::DownloadCachePiece);
108        assert_eq!(Tag::from(5), Tag::CachePieceContent);
109        assert_eq!(Tag::from(6), Tag::Reserved(6));
110        assert_eq!(Tag::from(253), Tag::Reserved(253));
111        assert_eq!(Tag::from(254), Tag::Close);
112        assert_eq!(Tag::from(255), Tag::Error);
113    }
114
115    #[test]
116    fn test_from_tag() {
117        assert_eq!(u8::from(Tag::DownloadPiece), 0);
118        assert_eq!(u8::from(Tag::PieceContent), 1);
119        assert_eq!(u8::from(Tag::DownloadPersistentCachePiece), 2);
120        assert_eq!(u8::from(Tag::PersistentCachePieceContent), 3);
121        assert_eq!(u8::from(Tag::DownloadCachePiece), 4);
122        assert_eq!(u8::from(Tag::CachePieceContent), 5);
123        assert_eq!(u8::from(Tag::Reserved(6)), 6);
124        assert_eq!(u8::from(Tag::Reserved(253)), 253);
125        assert_eq!(u8::from(Tag::Close), 254);
126        assert_eq!(u8::from(Tag::Error), 255);
127    }
128}