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_persistent_piece;
22pub mod download_piece;
23pub mod error;
24pub mod persistent_cache_piece_content;
25pub mod persistent_piece_content;
26pub mod piece_content;
27
28/// Tag Definitions
29#[repr(u8)]
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub enum Tag {
32    /// Download the content of a piece from a peer. It is composed of `{Task ID}{Piece ID}`,
33    /// where the Task ID is a SHA-256 value and the Piece ID is a number.
34    DownloadPiece = 0,
35
36    /// The content of a piece, with a maximum size of 4 GiB per piece.
37    PieceContent = 1,
38
39    /// Download the content of a persistent piece from a peer. It is composed of `{Task ID}{Piece ID}`,
40    /// where the Task ID is a SHA-256 value and the Piece ID is a number.
41    DownloadPersistentPiece = 2,
42
43    /// The content of a persistent piece, with a maximum size of 4 GiB per piece.
44    PersistentPieceContent = 3,
45
46    /// Download the content of a persistent cache piece from a peer. It is composed of `{Task ID}{Piece ID}`,
47    /// where the Task ID is a SHA-256 value and the Piece ID is a number.
48    DownloadPersistentCachePiece = 4,
49
50    /// The content of a persistent cache piece, with a maximum size of 4 GiB per piece.
51    PersistentCachePieceContent = 5,
52
53    /// Download the content of a cache piece from a peer. It is composed of `{Task ID}{Piece ID}`,
54    /// where the Task ID is a SHA-256 value and the Piece ID is a number.
55    DownloadCachePiece = 6,
56
57    /// The content of a cache piece, with a maximum size of 4 GiB per piece.
58    CachePieceContent = 7,
59
60    /// Reserved for future use, for tags 6-254.
61    Reserved(u8),
62
63    /// Close the connection. If server or client receives this tag, it will close the connection.
64    Close = 254,
65
66    /// Error message.
67    Error = 255,
68}
69
70/// Implement TryFrom<u8> for Tag.
71impl From<u8> for Tag {
72    /// Converts a u8 to a Tag enum.
73    fn from(value: u8) -> Self {
74        match value {
75            0 => Tag::DownloadPiece,
76            1 => Tag::PieceContent,
77            2 => Tag::DownloadPersistentPiece,
78            3 => Tag::PersistentPieceContent,
79            4 => Tag::DownloadPersistentCachePiece,
80            5 => Tag::PersistentCachePieceContent,
81            6 => Tag::DownloadCachePiece,
82            7 => Tag::CachePieceContent,
83            8..=253 => Tag::Reserved(value),
84            254 => Tag::Close,
85            255 => Tag::Error,
86        }
87    }
88}
89
90/// Implement From<Tag> for u8.
91impl From<Tag> for u8 {
92    /// Converts a Tag enum to a u8.
93    fn from(tag: Tag) -> Self {
94        match tag {
95            Tag::DownloadPiece => 0,
96            Tag::PieceContent => 1,
97            Tag::DownloadPersistentPiece => 2,
98            Tag::PersistentPieceContent => 3,
99            Tag::DownloadPersistentCachePiece => 4,
100            Tag::PersistentCachePieceContent => 5,
101            Tag::DownloadCachePiece => 6,
102            Tag::CachePieceContent => 7,
103            Tag::Reserved(value) => value,
104            Tag::Close => 254,
105            Tag::Error => 255,
106        }
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn test_try_from_u8() {
116        assert_eq!(Tag::from(0), Tag::DownloadPiece);
117        assert_eq!(Tag::from(1), Tag::PieceContent);
118        assert_eq!(Tag::from(2), Tag::DownloadPersistentPiece);
119        assert_eq!(Tag::from(3), Tag::PersistentPieceContent);
120        assert_eq!(Tag::from(4), Tag::DownloadPersistentCachePiece);
121        assert_eq!(Tag::from(5), Tag::PersistentCachePieceContent);
122        assert_eq!(Tag::from(6), Tag::DownloadCachePiece);
123        assert_eq!(Tag::from(7), Tag::CachePieceContent);
124        assert_eq!(Tag::from(8), Tag::Reserved(8));
125        assert_eq!(Tag::from(253), Tag::Reserved(253));
126        assert_eq!(Tag::from(254), Tag::Close);
127        assert_eq!(Tag::from(255), Tag::Error);
128    }
129
130    #[test]
131    fn test_from_tag() {
132        assert_eq!(u8::from(Tag::DownloadPiece), 0);
133        assert_eq!(u8::from(Tag::PieceContent), 1);
134        assert_eq!(u8::from(Tag::DownloadPersistentPiece), 2);
135        assert_eq!(u8::from(Tag::PersistentPieceContent), 3);
136        assert_eq!(u8::from(Tag::DownloadPersistentCachePiece), 4);
137        assert_eq!(u8::from(Tag::PersistentCachePieceContent), 5);
138        assert_eq!(u8::from(Tag::DownloadCachePiece), 6);
139        assert_eq!(u8::from(Tag::CachePieceContent), 7);
140        assert_eq!(u8::from(Tag::Reserved(8)), 8);
141        assert_eq!(u8::from(Tag::Reserved(253)), 253);
142        assert_eq!(u8::from(Tag::Close), 254);
143        assert_eq!(u8::from(Tag::Error), 255);
144    }
145}