dtp/
lib.rs

1// dtp/src/lib.rs
2
3// The core of your library depends on the `bytes` crate for efficient payload handling
4// and `dev_utils` for formatting in the Display implementation.
5use bytes::Bytes;
6use dev_utils::format::*;
7use std::fmt::{self, Display, Formatter};
8
9
10// Main layers (modules)
11pub mod datalink;
12pub mod network;
13pub mod transport;
14
15
16// --- GENERIC BUILDING BLOCKS ---
17
18/// A generic container for a source and destination address pair.
19pub type AddressPair<A> = (A, A);
20
21/// A generic header containing a pair of addresses.
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub struct Header<A> {
24    pub addresses: AddressPair<A>,
25}
26
27impl<A> Header<A> {
28    /// Creates a new header with source and destination addresses.
29    pub fn new(src: A, dst: A) -> Self {
30        Self {
31            addresses: (src, dst),
32        }
33    }
34    /// Returns a reference to the source address.
35    pub fn src(&self) -> &A {
36        &self.addresses.0
37    }
38    /// Returns a reference to the destination address.
39    pub fn dst(&self) -> &A {
40        &self.addresses.1
41    }
42}
43
44/// A macro to quickly define address types and their default `Header` implementations.
45macro_rules! define_addresses {
46    ($($(#[$meta_d:meta])* $name:ident: $inner:ty, $default:expr),* $(,)?) => {
47        $(
48            $(#[$meta_d])*
49            pub type $name = $inner;
50
51            impl Default for Header<$name> {
52                fn default() -> Self {
53                    let default_addr: $name = $default;
54                    Self {addresses: (default_addr, default_addr),}
55                }
56            }
57        )*
58    };
59}
60
61// Define the concrete address types used in the protocol stack.
62define_addresses! {
63    /// Represents a Data Link Layer MAC address ([u8; 6]).
64    MacAddress: [u8; 6], [0, 0, 0, 0, 0, 0],
65    /// Represents a Network Layer IPv4 address (u32).
66    Ipv4Address: u32, 0x7F000001, // 127.0.0.1
67    /// Represents a Transport Layer Port address (u16).
68    PortAddress: u16, 80,
69}
70
71/// A macro to implement the `IntoIterator` trait for the layered structs,
72/// allowing easy iteration over their payloads.
73macro_rules! impl_iterator_trait {
74    ($name:ident, $payload_field:ident, $payload_ty:ty) => {
75        // Implementation for consuming iteration: `for item in layer_struct { ... }`
76        impl IntoIterator for $name {
77            type Item = <$payload_ty as IntoIterator>::Item;
78            type IntoIter = <$payload_ty as IntoIterator>::IntoIter;
79
80            fn into_iter(self) -> Self::IntoIter {
81                self.$payload_field.into_iter()
82            }
83        }
84
85        // Implementation for borrowing iteration: `for item in &layer_struct { ... }`
86        impl<'a> IntoIterator for &'a $name {
87            type Item = &'a <$payload_ty as IntoIterator>::Item;
88            type IntoIter = std::slice::Iter<'a, <$payload_ty as IntoIterator>::Item>;
89
90            fn into_iter(self) -> Self::IntoIter {
91                self.$payload_field.iter()
92            }
93        }
94    };
95}
96
97/// A macro to define a protocol layer struct (`Frame`, `Packet`, `Segment`).
98/// This reduces boilerplate by creating the struct definition, `new` and `Default`
99/// implementations, a rich `Display` implementation, and iterator support.
100macro_rules! define_layer_struct {
101    (
102        $(
103            $(#[$meta:meta])*
104            $name:ident { header: $header_ty:ty, $payload_field:ident: $payload_ty:ty $(,)? }
105        ),* $(,)?
106    ) => {
107        $(
108            $(#[$meta])*
109            #[derive(Clone, PartialEq, Debug)]
110            pub struct $name {
111                pub header: Header<$header_ty>,
112                pub $payload_field: $payload_ty,
113            }
114
115            impl $name {
116                /// Constructs a new instance of the layer.
117                pub fn new(header: Header<$header_ty>, $payload_field: $payload_ty) -> Self {
118                    Self {
119                        header,
120                        $payload_field,
121                    }
122                }
123            }
124
125            impl Default for $name {
126                fn default() -> Self {
127                    Self {
128                        header: Header::<$header_ty>::default(),
129                        $payload_field: Default::default(),
130                    }
131                }
132            }
133
134            impl Display for $name {
135                fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
136                    writeln!( f, "{}", format!(
137                        "src: {:X?} -> dst: {:X?} | {:>4} {} |",
138                        self.header.addresses.0,
139                        self.header.addresses.1,
140                        self.$payload_field.len(),
141                        // A bit of a trick to get a plural 's' correctly
142                        if self.$payload_field.len() == 1 { stringify!($payload_field).trim_end_matches('s') } else { stringify!($payload_field) }
143                    ).style(Style::Italic)
144                    )?;
145                    for (idx, item) in self.$payload_field.iter().enumerate() {
146                        // Recursively print the nested layers with indentation
147                        let item_str = format!("{}", item);
148                        for line in item_str.lines() {
149                             writeln!(f, "\t{}", line)?;
150                        }
151                    }
152                    Ok(())
153                }
154            }
155
156            // Implement iteration for the struct
157            impl_iterator_trait!($name, $payload_field, $payload_ty);
158        )*
159    }
160}
161
162
163// --- PROTOCOL STACK DEFINITIONS ---
164
165define_layer_struct! {
166    /// Represents a Transport Layer Segment. It carries the raw application data payload.
167    Segment { header: PortAddress, payload: Bytes },
168
169    /// Represents a Network Layer Packet. It contains one or more `Segment`s.
170    Packet { header: Ipv4Address, pdu: Vec<Segment> },
171
172    /// Represents a Data Link Layer Frame. This is the final container, holding one or more `Packet`s.
173    Frame { header: MacAddress, network_pdu: Vec<Packet> },
174}
175
176
177// --- CORE TRAITS ---
178
179/// A trait for types that can be serialized into a byte vector.
180pub trait ToBytes {
181    /// Converts the structure to a byte representation.
182    fn to_bytes(&self) -> Vec<u8>;
183}
184
185/// A trait for getting size information about a network layer.
186pub trait LayerSize {
187    /// Returns the size of the payload in bytes.
188    fn payload_size(&self) -> usize;
189    /// Returns the total size of the layer, including headers.
190    fn total_size(&self) -> usize;
191}
192
193/// A generic builder trait.
194pub trait LayerBuilder {
195    type Output;
196    /// Builds the final output from the builder's configuration.
197    fn build(&self) -> Self::Output;
198}