leodos_protocols/transport/cfdp/pdu/file_directive/
prompt.rs1use crate::transport::cfdp::CfdpError;
2use crate::transport::cfdp::pdu::EntityId;
3use crate::transport::cfdp::pdu::Pdu;
4use crate::transport::cfdp::pdu::PduHeaderFixedPart;
5use crate::transport::cfdp::pdu::TransactionSeqNum;
6use crate::transport::cfdp::pdu::file_directive::DirectiveCode;
7use crate::transport::cfdp::pdu::file_directive::FileDirectivePdu;
8use crate::transport::cfdp::pdu::header::Direction;
9use crate::transport::cfdp::pdu::header::PduType;
10use crate::transport::cfdp::pdu::header::TransmissionMode;
11use crate::utils::get_bits_u8;
12use crate::utils::set_bits_u8;
13
14use bon::bon;
15use zerocopy::FromBytes;
16use zerocopy::Immutable;
17use zerocopy::IntoBytes;
18use zerocopy::KnownLayout;
19use zerocopy::Unaligned;
20
21#[repr(C)]
35#[derive(Debug, FromBytes, IntoBytes, Unaligned, KnownLayout, Immutable)]
36pub struct PromptPdu {
37 packed_flags: u8,
39}
40
41#[rustfmt::skip]
42mod bitmasks {
44 pub const PROMPT_RESPONSE_REQUIRED_MASK: u8 = 0b_10000000;
46 pub const _PROMPT_RESPONSE_RESERVED: u8 = 0b_01111111;
48}
49
50use bitmasks::*;
51
52#[derive(Debug, PartialEq, Eq)]
54pub enum PromptResponse {
55 KeepAlive,
57 Nak,
59}
60
61impl PromptPdu {
62 pub fn prompt_response(&self) -> PromptResponse {
64 if get_bits_u8(self.packed_flags, PROMPT_RESPONSE_REQUIRED_MASK) == 1 {
65 PromptResponse::KeepAlive
66 } else {
67 PromptResponse::Nak
68 }
69 }
70
71 pub fn set_prompt_response(&mut self, response: PromptResponse) {
73 let response_bit = match response {
74 PromptResponse::Nak => 0,
75 PromptResponse::KeepAlive => 1,
76 };
77 set_bits_u8(
78 &mut self.packed_flags,
79 PROMPT_RESPONSE_REQUIRED_MASK,
80 response_bit,
81 );
82 }
83}
84
85#[bon]
86impl PromptPdu {
87 #[builder]
89 pub fn new<'a>(
90 buffer: &'a mut [u8],
91 source_entity_id: EntityId,
92 dest_entity_id: EntityId,
93 transaction_seq_num: TransactionSeqNum,
94 transmission_mode: TransmissionMode,
95 crc_flag: bool,
96 response_required: PromptResponse,
97 ) -> Result<&'a mut Pdu, CfdpError> {
98 let data_field_len = (DirectiveCode::size() + size_of::<Self>()) as u16;
99
100 let header = PduHeaderFixedPart::builder()
101 .version(1)
102 .pdu_type(PduType::FileDirective)
103 .direction(Direction::TowardReceiver) .tx_mode(transmission_mode)
105 .crc_flag(crc_flag)
106 .large_file_flag(false) .data_field_len(data_field_len)
108 .seg_ctrl(false)
109 .seg_meta_flag(false)
110 .build()?;
111
112 let pdu = Pdu::builder()
113 .buffer(buffer)
114 .header_fixed(header)
115 .source_entity_id(source_entity_id)
116 .destination_entity_id(dest_entity_id)
117 .transaction_seq_num(transaction_seq_num)
118 .build()?;
119
120 let data_field = pdu.data_field_mut().unwrap();
121 let directive_pdu = FileDirectivePdu::mut_from_bytes(data_field).unwrap();
122 directive_pdu.set_directive_code(DirectiveCode::Prompt);
123
124 let prompt_pdu = PromptPdu::mut_from_bytes(&mut directive_pdu.rest).unwrap();
125 prompt_pdu.set_prompt_response(response_required);
126
127 Ok(pdu)
128 }
129}