1use crate::error::{CcsdsNdmError, Result, ValidationError};
6use crate::traits::Validate;
7use std::cell::{Cell, RefCell};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum ValidationMode {
11 Strict,
12 Lenient,
13}
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub enum MessageKind {
17 Opm,
18 Omm,
19 Oem,
20 Ocm,
21 Acm,
22 Aem,
23 Apm,
24 Cdm,
25 Tdm,
26 Rdm,
27 Ndm,
28}
29
30#[derive(Debug, Clone)]
31pub struct ValidationIssue {
32 pub message_kind: MessageKind,
33 pub error: ValidationError,
34}
35
36thread_local! {
37 static VALIDATION_MODE: Cell<ValidationMode> = const { Cell::new(ValidationMode::Strict) };
38 static VALIDATION_WARNINGS: RefCell<Vec<ValidationIssue>> = const { RefCell::new(Vec::new()) };
39}
40
41pub fn current_mode() -> ValidationMode {
42 VALIDATION_MODE.with(|mode| mode.get())
43}
44
45pub fn with_validation_mode<T>(mode: ValidationMode, f: impl FnOnce() -> Result<T>) -> Result<T> {
46 struct Guard {
47 prev: ValidationMode,
48 }
49
50 let prev = VALIDATION_MODE.with(|m| {
51 let prev = m.get();
52 m.set(mode);
53 prev
54 });
55
56 let _guard = Guard { prev };
57 let res = f();
58
59 VALIDATION_MODE.with(|m| m.set(_guard.prev));
60 res
61}
62
63pub fn take_warnings() -> Vec<ValidationIssue> {
64 VALIDATION_WARNINGS.with(|warnings| warnings.borrow_mut().drain(..).collect())
65}
66
67pub fn validate_with_mode(kind: MessageKind, value: &impl Validate) -> Result<()> {
68 match value.validate() {
69 Ok(()) => Ok(()),
70 Err(err) => handle_validation_error(kind, err),
71 }
72}
73
74pub fn handle_validation_error(kind: MessageKind, err: CcsdsNdmError) -> Result<()> {
75 match err {
76 CcsdsNdmError::Validation(val) => handle_validation_error_inner(kind, *val),
77 other => Err(other),
78 }
79}
80
81fn handle_validation_error_inner(kind: MessageKind, err: ValidationError) -> Result<()> {
82 match current_mode() {
83 ValidationMode::Strict => Err(err.into()),
84 ValidationMode::Lenient => {
85 VALIDATION_WARNINGS.with(|warnings| {
86 warnings.borrow_mut().push(ValidationIssue {
87 message_kind: kind,
88 error: err,
89 });
90 });
91 Ok(())
92 }
93 }
94}