cstring_array/
error.rs

1// SPDX-FileCopyrightText: 2025 RAprogramm <andrey.rozanov.vl@gmail.com>
2//
3// SPDX-License-Identifier: MIT
4
5//! Error types for CStringArray operations.
6//!
7//! This module provides the error types used throughout the crate when string
8//! array operations fail. All errors implement the standard `Error` trait for
9//! proper error handling and propagation.
10
11#[cfg(test)]
12use std::ffi::CString;
13use std::{
14    error::Error,
15    ffi::NulError,
16    fmt::{Display, Formatter, Result as FmtResult}
17};
18
19/// Error type for CStringArray operations
20#[derive(Debug)]
21pub enum CStringArrayError {
22    /// String contains an interior null byte
23    NulError(NulError),
24    /// Empty string array is not allowed
25    EmptyArray
26}
27
28impl Display for CStringArrayError {
29    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
30        use CStringArrayError::*;
31        match self {
32            NulError(e) => {
33                write!(
34                    f,
35                    "String contains interior null byte at position {}",
36                    e.nul_position()
37                )
38            }
39            EmptyArray => write!(f, "Cannot create array from empty input")
40        }
41    }
42}
43
44impl Error for CStringArrayError {
45    fn source(&self) -> Option<&(dyn Error + 'static)> {
46        use CStringArrayError::*;
47        match self {
48            NulError(e) => Some(e),
49            EmptyArray => None
50        }
51    }
52}
53
54impl From<NulError> for CStringArrayError {
55    fn from(err: NulError) -> Self {
56        Self::NulError(err)
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn test_nul_error_display() {
66        let test_string = "hello\0world";
67        let nul_err = match CString::new(test_string) {
68            Err(e) => e,
69            Ok(_) => panic!("Expected NulError")
70        };
71
72        let err = CStringArrayError::from(nul_err);
73        let display = format!("{}", err);
74        assert!(display.contains("interior null byte"));
75        assert!(display.contains("position 5"));
76    }
77
78    #[test]
79    fn test_empty_array_display() {
80        use CStringArrayError::*;
81        let err = EmptyArray;
82        assert_eq!(format!("{}", err), "Cannot create array from empty input");
83    }
84
85    #[test]
86    fn test_error_source_nul() {
87        let test_string = "test\0data";
88        let nul_err = CString::new(test_string).unwrap_err();
89        let err = CStringArrayError::from(nul_err);
90
91        assert!(err.source().is_some());
92        let source = err.source().unwrap();
93        assert!(source.is::<NulError>());
94    }
95
96    #[test]
97    fn test_error_source_empty() {
98        use CStringArrayError::*;
99        let err = EmptyArray;
100        assert!(err.source().is_none());
101    }
102
103    #[test]
104    fn test_from_nul_error() {
105        use CStringArrayError::*;
106        let nul_err = CString::new("a\0b").unwrap_err();
107        let err: CStringArrayError = nul_err.into();
108
109        match err {
110            NulError(e) => {
111                assert_eq!(e.nul_position(), 1);
112            }
113            _ => panic!("Expected NulError variant")
114        }
115    }
116
117    #[test]
118    fn test_debug_format() {
119        use CStringArrayError::*;
120        let err1 = EmptyArray;
121        let debug_str = format!("{:?}", err1);
122        assert!(debug_str.contains("EmptyArray"));
123
124        let nul_err = CString::new("x\0y").unwrap_err();
125        let err2 = CStringArrayError::from(nul_err);
126        let debug_str2 = format!("{:?}", err2);
127        assert!(debug_str2.contains("NulError"));
128    }
129}