Skip to main content

uls_db/
enum_adapters.rs

1//! Database adapters for enum columns.
2//!
3//! These helpers read integer-encoded enum columns from database rows
4//! and convert them back to their string/char representations.
5
6use rusqlite::Row;
7use uls_core::codes::{LicenseStatus, OperatorClass, RadioService};
8
9/// Read a license_status column (stored as INTEGER) and return as char.
10///
11/// Returns '?' if the value is NULL or unrecognized.
12pub fn read_license_status(row: &Row, idx: usize) -> rusqlite::Result<char> {
13    let code: Option<i64> = row.get(idx)?;
14    Ok(code
15        .and_then(|c| LicenseStatus::from_u8(c as u8))
16        .map(|s| s.as_str().chars().next().unwrap_or('?'))
17        .unwrap_or('?'))
18}
19
20/// Read a radio_service_code column (stored as INTEGER) and return as String.
21///
22/// Returns empty string if the value is NULL or unrecognized.
23pub fn read_radio_service(row: &Row, idx: usize) -> rusqlite::Result<String> {
24    let code: Option<i64> = row.get(idx)?;
25    Ok(code
26        .and_then(|c| RadioService::from_u8(c as u8))
27        .map(|r| r.as_str().to_string())
28        .unwrap_or_default())
29}
30
31/// Read an operator_class column (stored as INTEGER) and return as `Option<char>.
32///
33/// Returns None if the value is NULL or unrecognized.
34pub fn read_operator_class(row: &Row, idx: usize) -> rusqlite::Result<Option<char>> {
35    let code: Option<i64> = row.get(idx)?;
36    Ok(code
37        .and_then(|c| OperatorClass::from_u8(c as u8))
38        .map(|o| o.as_str().chars().next().unwrap_or('?')))
39}
40
41#[cfg(test)]
42mod tests {
43    // Note: These would require mocking rusqlite::Row which is complex.
44    // The actual behavior is tested via integration tests.
45}