leodos_protocols/transport/cfdp/pdu/tlv/
mod.rs1pub mod entity_id;
3pub mod fault_handler_override;
5pub mod filestore_request;
7pub mod filestore_response;
9pub mod flow_label;
11pub mod message_to_user;
13
14use zerocopy::FromBytes;
15use zerocopy::Immutable;
16use zerocopy::IntoBytes;
17use zerocopy::KnownLayout;
18use zerocopy::Unaligned;
19
20use crate::transport::cfdp::pdu::CfdpError;
21
22#[repr(C)]
25#[derive(FromBytes, IntoBytes, Unaligned, Immutable, KnownLayout)]
26pub struct Tlv {
27 tlv_type: u8,
29 length: u8,
31 value: [u8],
33}
34
35impl Tlv {
36 pub fn tlv_type(&self) -> Result<TlvType, CfdpError> {
38 TlvType::try_from(self.tlv_type)
39 }
40 pub fn set_type(&mut self, tlv_type: TlvType) {
42 self.tlv_type = tlv_type as u8;
43 }
44
45 pub fn length(&self) -> usize {
47 self.length as usize
48 }
49 pub fn set_length(&mut self, length: usize) -> Result<(), CfdpError> {
51 if length > u8::MAX as usize {
52 return Err(CfdpError::Custom("Length exceeds maximum value for TLV"));
53 }
54 self.length = length as u8;
55 Ok(())
56 }
57
58 pub fn value(&self) -> &[u8] {
60 &self.value
61 }
62 pub fn set_value(&mut self, value: &[u8]) -> Result<(), CfdpError> {
64 let len = value.len();
65 self.value
66 .get_mut(..len)
67 .ok_or(CfdpError::Custom("Value length exceeds allocated size"))?
68 .copy_from_slice(value);
69 Ok(())
70 }
71
72 pub fn total_len(&self) -> usize {
74 2 + self.length() }
76}
77
78#[derive(Debug, Copy, Clone, PartialEq, Eq)]
80pub enum TlvType {
81 FilestoreRequest = 0x00,
83 FilestoreResponse = 0x01,
85 MessageToUser = 0x02,
87 FaultHandlerOverride = 0x04,
90 FlowLabel = 0x05,
92 EntityId = 0x06,
94}
95
96impl TryFrom<u8> for TlvType {
97 type Error = CfdpError;
98
99 fn try_from(value: u8) -> Result<Self, Self::Error> {
100 match value {
101 0x00 => Ok(TlvType::FilestoreRequest),
102 0x01 => Ok(TlvType::FilestoreResponse),
103 0x02 => Ok(TlvType::MessageToUser),
104 0x04 => Ok(TlvType::FaultHandlerOverride),
105 0x05 => Ok(TlvType::FlowLabel),
106 0x06 => Ok(TlvType::EntityId),
107 _ => Err(CfdpError::Custom("Unknown TLV type")),
108 }
109 }
110}
111
112pub struct TlvIterator<'a> {
114 pub buffer: &'a [u8],
116}
117
118impl<'a> Iterator for TlvIterator<'a> {
119 type Item = &'a Tlv;
120
121 fn next(&mut self) -> Option<Self::Item> {
122 if self.buffer.len() < 2 {
123 return None;
124 }
125 let length = self.buffer[1] as usize;
126 let total_len = 2 + length;
127 if self.buffer.len() < total_len {
128 self.buffer = &[];
129 return None;
130 }
131 let (tlv_bytes, rest) = self.buffer.split_at(total_len);
132 let tlv = Tlv::ref_from_bytes(tlv_bytes).ok()?;
133 self.buffer = rest;
134
135 Some(tlv)
136 }
137}
138
139#[derive(Debug, Copy, Clone, PartialEq, Eq)]
141#[repr(u8)]
142pub enum FilestoreAction {
143 CreateFile = 0x00,
145 DeleteFile = 0x01,
147 RenameFile = 0x02,
149 AppendFile = 0x03,
151 ReplaceFile = 0x04,
153 CreateDirectory = 0x05,
155 RemoveDirectory = 0x06,
157 DenyFile = 0x07,
159 DenyDirectory = 0x08,
161}
162
163impl TryFrom<u8> for FilestoreAction {
164 type Error = CfdpError;
165 fn try_from(value: u8) -> Result<Self, Self::Error> {
166 match value {
167 0x00 => Ok(Self::CreateFile),
168 0x01 => Ok(Self::DeleteFile),
169 0x02 => Ok(Self::RenameFile),
170 0x03 => Ok(Self::AppendFile),
171 0x04 => Ok(Self::ReplaceFile),
172 0x05 => Ok(Self::CreateDirectory),
173 0x06 => Ok(Self::RemoveDirectory),
174 0x07 => Ok(Self::DenyFile),
175 0x08 => Ok(Self::DenyDirectory),
176 _ => Err(CfdpError::Custom("Invalid FilestoreAction code")),
177 }
178 }
179}