1use std::collections::HashMap;
2use std::sync::LazyLock;
3
4use regex::Regex;
5
6use crate::encoding::HL7Encoding;
7use crate::error::Hl7Error;
8use crate::field::Field;
9use crate::helper;
10use crate::segment::Segment;
11
12static SEGMENT_REGEX: LazyLock<Regex> =
13 LazyLock::new(|| Regex::new(r"^([A-Z][A-Z][A-Z1-9])([\(\[]([0-9]+)[\)\]]){0,1}$").unwrap());
14static FIELD_REGEX: LazyLock<Regex> =
15 LazyLock::new(|| Regex::new(r"^([0-9]+)([\(\[]([0-9]+)[\)\]]){0,1}$").unwrap());
16static OTHER_REGEX: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^[1-9]([0-9]{1,2})?$").unwrap());
17
18#[derive(Debug, Clone, Default)]
21pub struct Message {
22 pub hl7_message: String,
24 pub version: String,
26 pub message_structure: String,
28 pub message_control_id: String,
30 pub processing_id: String,
32 pub segment_count: usize,
34 pub encoding: HL7Encoding,
36
37 segments: HashMap<String, Vec<Segment>>,
38 all_segments: Vec<String>,
39}
40
41impl Message {
42 pub fn new() -> Self {
44 Self::default()
45 }
46
47 pub fn with_message(text: impl Into<String>) -> Self {
49 Self { hl7_message: text.into(), ..Self::default() }
50 }
51
52 pub fn parse_str(text: impl Into<String>, bypass_validation: bool) -> Result<Self, Hl7Error> {
54 let mut msg = Self::with_message(text);
55 msg.parse(bypass_validation)?;
56 Ok(msg)
57 }
58
59 pub fn parse(&mut self, bypass_validation: bool) -> Result<bool, Hl7Error> {
67 let is_valid = if bypass_validation { true } else { self.validate_message()? };
68
69 if !is_valid {
70 return Ok(false);
71 }
72
73 if self.all_segments.is_empty() {
74 self.all_segments = helper::split_message(&self.hl7_message);
75 }
76
77 let enc = self.encoding.clone();
78 self.segments.clear();
79 self.segment_count = 0;
80
81 let lines = self.all_segments.clone();
82 for line in lines {
83 if line.trim().is_empty() {
84 continue;
85 }
86
87 let segment = Segment::parse(&line, &enc).map_err(|e| {
88 Hl7Error::with_code(
89 format!("Failed to parse the message with error - {}", e.message),
90 Hl7Error::PARSING_ERROR,
91 )
92 })?;
93 self.add_new_segment(segment);
94 }
95
96 let serialized = self.serialize().map_err(|e| {
97 Hl7Error::with_code(
98 format!("Failed to serialize parsed message with error - {}", e.message),
99 Hl7Error::PARSING_ERROR,
100 )
101 })?;
102
103 if serialized.is_empty() {
104 return Err(Hl7Error::with_code(
105 "Unable to serialize to original message - ",
106 Hl7Error::PARSING_ERROR,
107 ));
108 }
109
110 self.encoding.evaluate_segment_delimiter(&self.hl7_message)?;
111
112 Ok(self.equals(&serialized))
113 }
114
115 pub fn serialize(&self) -> Result<String, Hl7Error> {
117 let mut out = String::new();
118 for seg in self.segments_in_order() {
119 seg.serialize(&mut out, &self.encoding);
120 }
121 Ok(out)
122 }
123
124 pub fn get_value(&self, path: &str) -> Result<String, Hl7Error> {
131 let parts: Vec<&str> = path.split('.').collect();
132 let com_count = parts.len();
133
134 if !validate_value_format(&parts) {
135 return Err(Hl7Error::new(format!("Request format is not valid: {path}")));
136 }
137
138 let caps = SEGMENT_REGEX
139 .captures(parts[0])
140 .ok_or_else(|| Hl7Error::new(format!("Request format is not valid: {path}")))?;
141 let seg_name = caps.get(1).map(|m| m.as_str()).unwrap_or("");
142 let mut occurrence = 0usize;
143 if let Some(m) = caps.get(3)
144 && let Ok(v) = m.as_str().parse::<usize>()
145 {
146 occurrence = v.saturating_sub(1);
147 }
148
149 let segment = self
150 .segments
151 .get(seg_name)
152 .and_then(|list| list.get(occurrence))
153 .ok_or_else(|| Hl7Error::new(format!("Segment name not available: {path}")))?;
154
155 let enc = &self.encoding;
156 let str_value: Option<String> = match com_count {
157 4 => {
158 let field = get_field(segment, parts[1]).map_err(|e| {
159 Hl7Error::new(format!("SubComponent not available - {path} Error: {}", e.message))
160 })?;
161 let ci = parse_index(parts[2])?;
162 let sci = parse_index(parts[3])?;
163 let comp = field.components.get(ci).ok_or_else(|| {
164 Hl7Error::new(format!("SubComponent not available - {path}"))
165 })?;
166 let sub = comp.sub_components.get(sci).ok_or_else(|| {
167 Hl7Error::new(format!("SubComponent not available - {path}"))
168 })?;
169 sub.value(enc)
170 }
171 3 => {
172 let field = get_field(segment, parts[1]).map_err(|e| {
173 Hl7Error::new(format!("Component not available - {path} Error: {}", e.message))
174 })?;
175 let ci = parse_index(parts[2])?;
176 let comp = field
177 .components
178 .get(ci)
179 .ok_or_else(|| Hl7Error::new(format!("Component not available - {path}")))?;
180 comp.value(enc)
181 }
182 2 => {
183 let field = get_field(segment, parts[1]).map_err(|e| {
184 Hl7Error::new(format!("Field not available - {path} Error: {}", e.message))
185 })?;
186 field.value(enc)
187 }
188 _ => segment.value(enc),
189 };
190
191 Ok(enc.decode(str_value.as_deref().unwrap_or("")))
192 }
193
194 pub fn set_value(&mut self, path: &str, value: &str) -> Result<bool, Hl7Error> {
196 let parts: Vec<&str> = path.split('.').collect();
197 let com_count = parts.len();
198
199 if !validate_value_format(&parts) {
200 return Err(Hl7Error::new("Request format is not valid"));
201 }
202
203 let seg_name = parts[0];
204 let enc = self.encoding.clone();
205
206 let list = self
207 .segments
208 .get_mut(seg_name)
209 .ok_or_else(|| Hl7Error::new("Segment name not available"))?;
210
211 let mut is_set = false;
212
213 for segment in list.iter_mut() {
214 match com_count {
215 4 => {
216 let ci = parse_index(parts[2])?;
217 let sci = parse_index(parts[3])?;
218 let field = get_field_mut(segment, parts[1]).map_err(|e| {
219 Hl7Error::new(format!(
220 "SubComponent not available - {path} Error: {}",
221 e.message
222 ))
223 })?;
224 let comp = field.components.get_mut(ci).ok_or_else(|| {
225 Hl7Error::new(format!("SubComponent not available - {path}"))
226 })?;
227 let sub = comp.sub_components.get_mut(sci).ok_or_else(|| {
228 Hl7Error::new(format!("SubComponent not available - {path}"))
229 })?;
230 sub.set_value(value);
231 is_set = true;
232 }
233 3 => {
234 let ci = parse_index(parts[2])?;
235 let field = get_field_mut(segment, parts[1]).map_err(|e| {
236 Hl7Error::new(format!("Component not available - {path} Error: {}", e.message))
237 })?;
238 let comp = field
239 .components
240 .get_mut(ci)
241 .ok_or_else(|| Hl7Error::new(format!("Component not available - {path}")))?;
242 comp.set_value(value, &enc);
243 is_set = true;
244 }
245 2 => {
246 let field = get_field_mut(segment, parts[1]).map_err(|e| {
247 Hl7Error::new(format!("Field not available - {path} Error: {}", e.message))
248 })?;
249 field.set_value(value, &enc);
250 is_set = true;
251 }
252 _ => return Err(Hl7Error::new("Cannot overwrite a segment value")),
253 }
254 }
255
256 Ok(is_set)
257 }
258
259 pub fn is_componentized(&self, path: &str) -> Result<bool, Hl7Error> {
261 let parts: Vec<&str> = path.split('.').collect();
262
263 if !validate_value_format(&parts) {
264 return Err(Hl7Error::new("Request format is not valid"));
265 }
266 if parts.len() < 2 {
267 return Err(Hl7Error::new("Field not identified in request"));
268 }
269
270 let segment = self
271 .segments
272 .get(parts[0])
273 .and_then(|list| list.first())
274 .ok_or_else(|| Hl7Error::new(format!("Field not available - {path}")))?;
275 let field = get_field(segment, parts[1])
276 .map_err(|e| Hl7Error::new(format!("Field not available - {path} Error: {}", e.message)))?;
277
278 Ok(field.is_componentized)
279 }
280
281 pub fn has_repetitions(&self, path: &str) -> Result<bool, Hl7Error> {
283 let parts: Vec<&str> = path.split('.').collect();
284
285 if !validate_value_format(&parts) {
286 return Err(Hl7Error::new("Request format is not valid"));
287 }
288 if parts.len() < 2 {
289 return Err(Hl7Error::new("Field not identified in request"));
290 }
291
292 let segment = self
293 .segments
294 .get(parts[0])
295 .and_then(|list| list.first())
296 .ok_or_else(|| Hl7Error::new(format!("Field not available - {path}")))?;
297 let count = get_field_repetitions(segment, parts[1])
298 .map_err(|e| Hl7Error::new(format!("Field not available - {path} Error: {}", e.message)))?;
299
300 Ok(count > 1)
301 }
302
303 pub fn is_subcomponentized(&self, path: &str) -> Result<bool, Hl7Error> {
305 let parts: Vec<&str> = path.split('.').collect();
306
307 if !validate_value_format(&parts) {
308 return Err(Hl7Error::new("Request format is not valid"));
309 }
310 if parts.len() < 3 {
311 return Err(Hl7Error::new("Component not identified in request"));
312 }
313
314 let segment = self
315 .segments
316 .get(parts[0])
317 .and_then(|list| list.first())
318 .ok_or_else(|| Hl7Error::new(format!("Component not available - {path}")))?;
319 let field = get_field(segment, parts[1]).map_err(|e| {
320 Hl7Error::new(format!("Component not available - {path} Error: {}", e.message))
321 })?;
322 let ci = parse_index(parts[2])?;
323 let comp = field
324 .components
325 .get(ci)
326 .ok_or_else(|| Hl7Error::new(format!("Component not available - {path}")))?;
327
328 Ok(comp.is_subcomponentized)
329 }
330
331 pub fn add_new_segment(&mut self, mut segment: Segment) -> bool {
335 segment.sequence_no = self.segment_count;
336 self.segment_count += 1;
337 self.segments.entry(segment.name.clone()).or_default().push(segment);
338 true
339 }
340
341 pub fn remove_segment(&mut self, segment_name: &str, index: usize) -> bool {
343 if let Some(list) = self.segments.get_mut(segment_name)
344 && index < list.len()
345 {
346 list.remove(index);
347 self.segment_count = self.segment_count.saturating_sub(1);
348 return true;
349 }
350 false
351 }
352
353 pub fn segments(&self) -> Vec<&Segment> {
355 self.segments_in_order()
356 }
357
358 pub fn segments_named(&self, segment_name: &str) -> Vec<&Segment> {
360 self.segments_in_order()
361 .into_iter()
362 .filter(|s| s.name == segment_name)
363 .collect()
364 }
365
366 pub fn default_segment(&self, segment_name: &str) -> Option<&Segment> {
368 self.segments_in_order().into_iter().find(|s| s.name == segment_name)
369 }
370
371 pub fn segments_named_mut(&mut self, segment_name: &str) -> Option<&mut Vec<Segment>> {
373 self.segments.get_mut(segment_name)
374 }
375
376 #[allow(clippy::too_many_arguments)]
378 pub fn add_segment_msh(
379 &mut self,
380 sending_application: &str,
381 sending_facility: &str,
382 receiving_application: &str,
383 receiving_facility: &str,
384 security: Option<&str>,
385 message_type: &str,
386 message_control_id: &str,
387 processing_id: &str,
388 version: &str,
389 ) -> Result<(), Hl7Error> {
390 let date_string = helper::now_long_date();
391 let delim = self.encoding.field_delimiter;
392 let all = self.encoding.all_delimiters();
393 let seg_delim = self.encoding.segment_delimiter.clone();
394
395 let mut response = String::new();
396 response.push_str("MSH");
397 response.push_str(&all);
398 response.push(delim);
399 response.push_str(sending_application);
400 response.push(delim);
401 response.push_str(sending_facility);
402 response.push(delim);
403 response.push_str(receiving_application);
404 response.push(delim);
405 response.push_str(receiving_facility);
406 response.push(delim);
407 response.push_str(&self.encoding.encode(&date_string));
408 response.push(delim);
409 response.push_str(security.unwrap_or(""));
410 response.push(delim);
411 response.push_str(message_type);
412 response.push(delim);
413 response.push_str(message_control_id);
414 response.push(delim);
415 response.push_str(processing_id);
416 response.push(delim);
417 response.push_str(version);
418 response.push_str(&seg_delim);
419
420 let message = Message::parse_str(response, false)?;
421 let msh = message
422 .default_segment("MSH")
423 .ok_or_else(|| Hl7Error::new("MSH segment not found"))?
424 .clone();
425 self.add_new_segment(msh);
426
427 Ok(())
428 }
429
430 pub fn get_ack(&self, bypass_validation: bool) -> Option<Message> {
434 self.create_ack_message("AA", false, None, bypass_validation)
435 }
436
437 pub fn get_nack(&self, code: &str, err_msg: &str, bypass_validation: bool) -> Option<Message> {
439 self.create_ack_message(code, true, Some(err_msg), bypass_validation)
440 }
441
442 pub fn get_mllp(&self) -> Result<Vec<u8>, Hl7Error> {
444 Ok(helper::get_mllp(&self.serialize()?))
445 }
446
447 fn create_ack_message(
448 &self,
449 code: &str,
450 is_nack: bool,
451 err_msg: Option<&str>,
452 bypass_validation: bool,
453 ) -> Option<Message> {
454 if self.message_structure == "ACK" {
455 return None;
456 }
457
458 let date_string = helper::now_long_date();
459 let msh = self.segments.get("MSH")?.first()?;
460 let delim = self.encoding.field_delimiter;
461 let all = self.encoding.all_delimiters();
462 let seg_delim = &self.encoding.segment_delimiter;
463
464 let field = |i: usize| -> String {
465 msh.fields.get(i).and_then(|f| f.value(&self.encoding)).unwrap_or_default()
466 };
467
468 let mut response = String::new();
469 response.push_str("MSH");
470 response.push_str(&all);
471 response.push(delim);
472 response.push_str(&field(4)); response.push(delim);
474 response.push_str(&field(5)); response.push(delim);
476 response.push_str(&field(2)); response.push(delim);
478 response.push_str(&field(3)); response.push(delim);
480 response.push_str(&date_string);
481 response.push(delim);
482 response.push(delim); response.push_str("ACK");
484 response.push(delim);
485 response.push_str(&self.message_control_id);
486 response.push(delim);
487 response.push_str(&self.processing_id);
488 response.push(delim);
489 response.push_str(&self.version);
490 response.push_str(seg_delim);
491
492 response.push_str("MSA");
493 response.push(delim);
494 response.push_str(code);
495 response.push(delim);
496 response.push_str(&self.message_control_id);
497 if is_nack {
498 response.push(delim);
499 response.push_str(err_msg.unwrap_or(""));
500 }
501 response.push_str(seg_delim);
502
503 Message::parse_str(response, bypass_validation).ok()
504 }
505
506 fn segments_in_order(&self) -> Vec<&Segment> {
509 let mut all: Vec<&Segment> = self.segments.values().flatten().collect();
510 all.sort_by_key(|s| s.sequence_no);
511 all
512 }
513
514 fn validate_message(&mut self) -> Result<bool, Hl7Error> {
518 self.validate_message_inner().map_err(|e| {
519 Hl7Error::with_code(
520 format!("Failed to validate the message with error - {}", e.message),
521 Hl7Error::BAD_MESSAGE,
522 )
523 })?;
524 Ok(true)
525 }
526
527 fn validate_message_inner(&mut self) -> Result<(), Hl7Error> {
528 if self.hl7_message.is_empty() {
529 return Err(Hl7Error::with_code("No Message Found", Hl7Error::BAD_MESSAGE));
530 }
531
532 if self.hl7_message.len() < 20 {
534 return Err(Hl7Error::with_code(
535 format!("Message Length too short: {} chars.", self.hl7_message.len()),
536 Hl7Error::BAD_MESSAGE,
537 ));
538 }
539
540 if !self.hl7_message.starts_with("MSH") {
541 return Err(Hl7Error::with_code(
542 "MSH segment not found at the beginning of the message",
543 Hl7Error::BAD_MESSAGE,
544 ));
545 }
546
547 self.encoding.evaluate_segment_delimiter(&self.hl7_message)?;
548 self.all_segments = helper::split_message(&self.hl7_message);
549 self.hl7_message =
550 self.all_segments.join(&self.encoding.segment_delimiter) + &self.encoding.segment_delimiter;
551
552 let first = &self.all_segments[0];
553 let field_delimiters: String = first.chars().skip(3).take(5).collect();
554 self.encoding.evaluate_delimiters(&field_delimiters)?;
555 self.decompose_multibyte_hex_sequences();
556
557 let fourth_char = self.hl7_message.chars().nth(3);
558
559 for segment in &self.all_segments {
560 if segment.trim().is_empty() {
561 continue;
562 }
563
564 let name: String = segment.chars().take(3).collect();
565 if !SEGMENT_REGEX.is_match(&name) {
566 return Err(Hl7Error::with_code(
567 format!("Invalid segment name found: {segment}"),
568 Hl7Error::BAD_MESSAGE,
569 ));
570 }
571
572 if segment.chars().count() > 3 && segment.chars().nth(3) != fourth_char {
573 return Err(Hl7Error::with_code(
574 format!("Invalid segment found: {segment}"),
575 Hl7Error::BAD_MESSAGE,
576 ));
577 }
578 }
579
580 let msh_line = &self.all_segments[0];
581 let field_sep_count = msh_line.chars().filter(|c| *c == self.encoding.field_delimiter).count();
582 if field_sep_count < 11 {
583 return Err(Hl7Error::with_code(
584 "MSH segment doesn't contain all the required fields",
585 Hl7Error::BAD_MESSAGE,
586 ));
587 }
588
589 let msh_fields: Vec<&str> = msh_line.split(self.encoding.field_delimiter).collect();
590
591 if msh_fields.len() >= 12 {
593 let decoded = self.encoding.decode(msh_fields[11]);
594 self.version =
595 decoded.split(self.encoding.component_delimiter).next().unwrap_or("").to_string();
596 } else {
597 return Err(Hl7Error::with_code(
598 "HL7 version not found in the MSH segment",
599 Hl7Error::REQUIRED_FIELD_MISSING,
600 ));
601 }
602
603 let msh_9 = self.encoding.decode(msh_fields[8]);
605 if msh_9.is_empty() {
606 return Err(Hl7Error::with_code(
607 "MSH.9 not available",
608 Hl7Error::UNSUPPORTED_MESSAGE_TYPE,
609 ));
610 }
611
612 let comps: Vec<&str> = msh_9.split(self.encoding.component_delimiter).collect();
613 if comps.len() >= 3 {
614 self.message_structure = comps[2].to_string();
615 } else if !comps.is_empty() && comps[0] == "ACK" {
616 self.message_structure = "ACK".to_string();
617 } else if comps.len() == 2 {
618 self.message_structure = format!("{}_{}", comps[0], comps[1]);
619 } else {
620 return Err(Hl7Error::with_code(
621 "Message Type & Trigger Event value not found in message",
622 Hl7Error::UNSUPPORTED_MESSAGE_TYPE,
623 ));
624 }
625
626 self.message_control_id = self.encoding.decode(msh_fields[9]);
628 if self.message_control_id.is_empty() {
629 return Err(Hl7Error::with_code(
630 "MSH.10 - Message Control ID not found",
631 Hl7Error::REQUIRED_FIELD_MISSING,
632 ));
633 }
634
635 self.processing_id = self.encoding.decode(msh_fields[10]);
637 if self.processing_id.is_empty() {
638 return Err(Hl7Error::with_code(
639 "MSH.11 - Processing ID not found",
640 Hl7Error::REQUIRED_FIELD_MISSING,
641 ));
642 }
643
644 Ok(())
645 }
646
647 fn equals(&self, other: &str) -> bool {
650 let seg_chars: Vec<char> = self.encoding.segment_delimiter.chars().collect();
651 let split = |s: &str| -> Vec<String> {
652 s.split(|c| seg_chars.contains(&c))
653 .filter(|p| !p.is_empty())
654 .map(str::to_string)
655 .collect()
656 };
657
658 let mut arr1 = split(&self.hl7_message);
659 let arr2 = split(other);
660
661 self.decode_hexa_sequences(&mut arr1, false);
662
663 arr1 == arr2
664 }
665
666 fn decompose_multibyte_hex_sequences(&mut self) {
667 if self.encoding.escape_character == '\0' || self.all_segments.is_empty() {
668 return;
669 }
670
671 let mut lines = std::mem::take(&mut self.all_segments);
672 let changed = self.decode_hexa_sequences(&mut lines, true);
673 self.all_segments = lines;
674
675 if changed {
676 self.hl7_message = self.all_segments.join(&self.encoding.segment_delimiter)
677 + &self.encoding.segment_delimiter;
678 }
679 }
680
681 fn decode_hexa_sequences(&self, lines: &mut [String], decompose: bool) -> bool {
685 let esc = self.encoding.escape_character;
686 let pattern = format!(r"\x{{{0:X}}}X([0-9A-Fa-f]*)\x{{{0:X}}}", esc as u32);
687 let re = match Regex::new(&pattern) {
688 Ok(r) => r,
689 Err(_) => return false,
690 };
691
692 let mut changed = false;
693
694 for line in lines.iter_mut() {
695 if !line.contains(esc) {
696 continue;
697 }
698
699 let replaced = re
700 .replace_all(line, |caps: ®ex::Captures| {
701 let whole = &caps[0];
702 let hex = caps.get(1).map(|m| m.as_str()).unwrap_or("");
703
704 if decompose {
705 decompose_multibyte_hex(whole, hex, esc)
706 } else if !is_encoded_linebreak_byte(hex) {
707 HL7Encoding::decode_hex_string(hex)
708 } else {
709 whole.to_string()
710 }
711 })
712 .into_owned();
713
714 if &replaced != line {
715 *line = replaced;
716 changed = true;
717 }
718 }
719
720 changed
721 }
722}
723
724fn parse_index(s: &str) -> Result<usize, Hl7Error> {
728 s.parse::<usize>()
729 .ok()
730 .and_then(|n| n.checked_sub(1))
731 .ok_or_else(|| Hl7Error::new(format!("Invalid index: {s}")))
732}
733
734fn parse_field_index(index: &str) -> Result<(usize, usize), Hl7Error> {
736 let caps = FIELD_REGEX
737 .captures(index)
738 .ok_or_else(|| Hl7Error::new("Invalid field index"))?;
739
740 let field_index = caps[1]
741 .parse::<usize>()
742 .ok()
743 .and_then(|n| n.checked_sub(1))
744 .ok_or_else(|| Hl7Error::new("Invalid field index"))?;
745
746 let repetition = match caps.get(3) {
747 Some(m) => m
748 .as_str()
749 .parse::<usize>()
750 .ok()
751 .and_then(|n| n.checked_sub(1))
752 .ok_or_else(|| Hl7Error::new("Invalid field index"))?,
753 None => 0,
754 };
755
756 Ok((field_index, repetition))
757}
758
759fn get_field<'a>(segment: &'a Segment, index: &str) -> Result<&'a Field, Hl7Error> {
762 let (field_index, repetition) = parse_field_index(index)?;
763 let field = segment
764 .fields
765 .get(field_index)
766 .ok_or_else(|| Hl7Error::new("Field not available"))?;
767
768 if field.has_repetitions {
769 field
770 .repetitions
771 .get(repetition)
772 .ok_or_else(|| Hl7Error::new("Field repetition not available"))
773 } else if repetition == 0 {
774 Ok(field)
775 } else {
776 Err(Hl7Error::new("Field repetition not available"))
777 }
778}
779
780fn get_field_mut<'a>(segment: &'a mut Segment, index: &str) -> Result<&'a mut Field, Hl7Error> {
782 let (field_index, repetition) = parse_field_index(index)?;
783 let field = segment
784 .fields
785 .get_mut(field_index)
786 .ok_or_else(|| Hl7Error::new("Field not available"))?;
787
788 if field.has_repetitions {
789 field
790 .repetitions
791 .get_mut(repetition)
792 .ok_or_else(|| Hl7Error::new("Field repetition not available"))
793 } else if repetition == 0 {
794 Ok(field)
795 } else {
796 Err(Hl7Error::new("Field repetition not available"))
797 }
798}
799
800fn get_field_repetitions(segment: &Segment, index: &str) -> Result<usize, Hl7Error> {
803 let caps = match FIELD_REGEX.captures(index) {
804 Some(c) => c,
805 None => return Ok(0),
806 };
807
808 let field_index = caps[1]
809 .parse::<usize>()
810 .ok()
811 .and_then(|n| n.checked_sub(1))
812 .ok_or_else(|| Hl7Error::new("Invalid field index"))?;
813
814 let field = segment
815 .fields
816 .get(field_index)
817 .ok_or_else(|| Hl7Error::new("Field not available"))?;
818
819 if field.has_repetitions {
820 Ok(field.repetitions.len())
821 } else {
822 Ok(1)
823 }
824}
825
826fn validate_value_format(parts: &[&str]) -> bool {
829 if parts.is_empty() || !SEGMENT_REGEX.is_match(parts[0]) {
830 return false;
831 }
832
833 let mut is_valid = false;
834 for (i, part) in parts.iter().enumerate().skip(1) {
835 let matches = (i == 1 && FIELD_REGEX.is_match(part))
836 || (i > 1 && OTHER_REGEX.is_match(part));
837
838 if matches {
839 is_valid = true;
840 } else {
841 return false;
842 }
843 }
844
845 is_valid
846}
847
848fn decompose_multibyte_hex(match_value: &str, hex: &str, esc: char) -> String {
852 if hex.len() <= 2 || !hex.len().is_multiple_of(2) || !contains_encoded_linebreak(hex) {
853 return match_value.to_string();
854 }
855
856 let mut result = String::with_capacity(match_value.len());
857 let mut i = 0;
858 while i + 2 <= hex.len() {
859 result.push(esc);
860 result.push('X');
861 result.push_str(&hex[i..i + 2]);
862 result.push(esc);
863 i += 2;
864 }
865
866 result
867}
868
869fn contains_encoded_linebreak(hex: &str) -> bool {
871 (0..hex.len() / 2).any(|i| is_encoded_linebreak_byte(&hex[i * 2..i * 2 + 2]))
872}
873
874fn is_encoded_linebreak_byte(hex: &str) -> bool {
876 matches!(hex, "0D" | "0A" | "0d" | "0a")
877}