milstd1553b_parser/
parser.rs

1//! High-level message parser for MIL-STD-1553B protocol
2
3use crate::core::{Bus, Word, WordType};
4use crate::encoding::{ManchesterDecoder, ManchesterEncoder};
5use crate::error::Result;
6use crate::message::{Command, Message, StatusWord};
7
8/// A parsed MIL-STD-1553B transaction
9#[derive(Debug, Clone)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct Transaction {
12    /// Bus on which the transaction occurred
13    pub bus: Bus,
14    /// The command/status message
15    pub message: Message,
16    /// Timestamp of the transaction (microseconds, if available)
17    pub timestamp_us: Option<u64>,
18}
19
20/// MIL-STD-1553B protocol parser
21pub struct Parser {
22    /// Current bus context
23    pub bus: Bus,
24}
25
26impl Parser {
27    /// Create a new parser
28    pub fn new(bus: Bus) -> Self {
29        Parser { bus }
30    }
31
32    /// Parse a single word from Manchester-encoded bytes
33    ///
34    /// Expects 5 bytes (40 bits) of Manchester-encoded data representing 20 bits
35    pub fn parse_word(&self, data: &[u8]) -> Result<Word> {
36        let word_value = ManchesterDecoder::decode_word(data)?;
37        // Try to determine word type from context or structure
38        self.identify_word_type_and_create(word_value)
39    }
40
41    /// Parse multiple words from raw data
42    pub fn parse_words(&self, data: &[u8]) -> Result<Vec<Word>> {
43        let mut words = Vec::new();
44        let mut offset = 0;
45
46        while offset + 5 <= data.len() {
47            let word = self.parse_word(&data[offset..offset + 5])?;
48            words.push(word);
49            offset += 5;
50        }
51
52        Ok(words)
53    }
54
55    /// Parse a command-response transaction
56    ///
57    /// A typical transaction consists of:
58    /// 1. Command word (from Bus Controller)
59    /// 2. Optional data words (if receive command)
60    /// 3. Status word (from Remote Terminal)
61    /// 4. Optional response data words
62    pub fn parse_transaction(&self, data: &[u8]) -> Result<Transaction> {
63        let words = self.parse_words(data)?;
64
65        if words.is_empty() {
66            return Err(crate::error::ParseError::insufficient_data(
67                "No words to parse".to_string(),
68            ));
69        }
70
71        // Identify the message structure
72        let message = self.parse_message(&words)?;
73
74        Ok(Transaction {
75            bus: self.bus,
76            message,
77            timestamp_us: None,
78        })
79    }
80
81    /// Parse a message from a sequence of words
82    fn parse_message(&self, words: &[Word]) -> Result<Message> {
83        if words.is_empty() {
84            return Err(crate::error::ParseError::insufficient_data(
85                "Empty word sequence".to_string(),
86            ));
87        }
88
89        let first_word = words[0];
90
91        match first_word.word_type() {
92            WordType::Command => {
93                let command = Command::from_word(&first_word)?;
94
95                // Check if there are data words following
96                if words.len() > 1 {
97                    let mut data_words = Vec::new();
98                    for word in &words[1..] {
99                        if word.word_type() == WordType::Data {
100                            data_words.push(*word);
101                        } else {
102                            break; // Stop at non-data word
103                        }
104                    }
105
106                    if !data_words.is_empty() {
107                        Ok(Message::CommandData {
108                            command,
109                            data_words,
110                        })
111                    } else {
112                        Ok(Message::CommandOnly(command))
113                    }
114                } else {
115                    Ok(Message::CommandOnly(command))
116                }
117            }
118            WordType::Status => {
119                let status = StatusWord::from_word(&first_word)?;
120                Ok(Message::Status(status))
121            }
122            _ => Err(crate::error::ParseError::invalid_message_type(
123                "Message must start with command or status word".to_string(),
124            )),
125        }
126    }
127
128    /// Identify word type and create a Word with appropriate type
129    fn identify_word_type_and_create(&self, word_value: u32) -> Result<Word> {
130        // Simple heuristic: analyze the word structure
131        // In a real implementation, this might be passed as a parameter
132        // or inferred from protocol context
133
134        // For now, create as data word - caller should specify type
135        Word::new(word_value, WordType::Data)
136    }
137
138    /// Encode and transmit a command
139    pub fn encode_command(&self, command: &Command) -> Result<Vec<u8>> {
140        let word = command.to_word()?;
141        let encoded = ManchesterEncoder::encode_word(word.data());
142        Ok(encoded)
143    }
144
145    /// Encode a status word
146    pub fn encode_status(&self, status: &StatusWord) -> Result<Vec<u8>> {
147        let word = status.to_word()?;
148        let encoded = ManchesterEncoder::encode_word(word.data());
149        Ok(encoded)
150    }
151
152    /// Encode data words
153    pub fn encode_data_words(&self, data: &[u16]) -> Result<Vec<u8>> {
154        let mut encoded = Vec::new();
155
156        for &value in data {
157            let parity = Word::calculate_parity(value) as u32;
158            let word_value = (parity << 17) | ((value as u32) << 1);
159            let word = Word::new(word_value, WordType::Data)?;
160
161            let word_encoded = ManchesterEncoder::encode_word(word.data());
162            encoded.extend(word_encoded);
163        }
164
165        Ok(encoded)
166    }
167}
168
169/// Builder for parsing MIL-STD-1553B data streams
170pub struct ParserBuilder {
171    bus: Bus,
172}
173
174impl ParserBuilder {
175    /// Create a new parser builder
176    pub fn new() -> Self {
177        ParserBuilder { bus: Bus::BusA }
178    }
179
180    /// Set the bus
181    pub fn with_bus(mut self, bus: Bus) -> Self {
182        self.bus = bus;
183        self
184    }
185
186    /// Build the parser
187    pub fn build(self) -> Parser {
188        Parser::new(self.bus)
189    }
190}
191
192impl Default for ParserBuilder {
193    fn default() -> Self {
194        Self::new()
195    }
196}
197
198#[cfg(test)]
199mod tests {
200    use super::*;
201    use crate::core::Address;
202    use crate::message::{CommandType, SubAddress};
203
204    #[test]
205    fn test_parser_creation() {
206        let parser = Parser::new(Bus::BusA);
207        assert_eq!(parser.bus, Bus::BusA);
208    }
209
210    #[test]
211    fn test_parser_builder() {
212        let parser = ParserBuilder::new().with_bus(Bus::BusB).build();
213        assert_eq!(parser.bus, Bus::BusB);
214    }
215
216    #[test]
217    fn test_encode_command() -> Result<()> {
218        let parser = Parser::new(Bus::BusA);
219        let cmd = Command::new(
220            Address::new(5)?,
221            CommandType::Transmit,
222            SubAddress::new(10)?,
223            16,
224        )?;
225
226        let encoded = parser.encode_command(&cmd)?;
227        assert!(!encoded.is_empty());
228        Ok(())
229    }
230
231    #[test]
232    fn test_parse_word_roundtrip() -> Result<()> {
233        let parser = Parser::new(Bus::BusA);
234
235        // Create a word
236        let original_data = 0x12345u32;
237        let parity = Word::calculate_parity(original_data as u16) as u32;
238        let word_value = (parity << 17) | (original_data << 1);
239        let original_word = Word::new(word_value, WordType::Data)?;
240
241        // Encode it
242        let encoded = ManchesterEncoder::encode_word(original_word.data());
243
244        // Decode it
245        let decoded_word = parser.parse_word(&encoded)?;
246
247        // Verify
248        assert_eq!(decoded_word.data(), original_word.data());
249        Ok(())
250    }
251}