Skip to main content

sz_configtool_lib/
hashes.rs

1//! Hash operations for SYS_OOM section
2//!
3//! Functions for managing NAME_HASH and SSN_LAST4_HASH arrays in the SYS_OOM section.
4//! These hashes control special matching behavior for common names and SSN last 4 digits.
5
6use crate::error::{Result, SzConfigError};
7use serde_json::{Value, json};
8
9/// Add a name to the NAME_HASH array
10///
11/// # Arguments
12///
13/// * `config_json` - Configuration JSON string
14/// * `name` - Name value to add
15///
16/// # Returns
17///
18/// Returns modified configuration JSON on success
19///
20/// # Example
21///
22/// ```
23/// use sz_configtool_lib::hashes;
24///
25/// let config = r#"{"G2_CONFIG": {"SYS_OOM": {"NAME_HASH": []}}}"#;
26/// let modified = hashes::add_to_name_hash(config, "JOHN").unwrap();
27/// ```
28pub fn add_to_name_hash(config_json: &str, name: &str) -> Result<String> {
29    let mut config_data: Value = serde_json::from_str(config_json)?;
30
31    if let Some(g2_config) = config_data.get_mut("G2_CONFIG") {
32        if let Some(sys_oom) = g2_config.get_mut("SYS_OOM") {
33            if let Some(sys_oom_obj) = sys_oom.as_object_mut() {
34                // Get or create NAME_HASH array
35                let name_hash = sys_oom_obj.entry("NAME_HASH").or_insert(json!([]));
36
37                if let Some(name_hash_arr) = name_hash.as_array_mut() {
38                    // Check if already exists
39                    if name_hash_arr.iter().any(|v| v.as_str() == Some(name)) {
40                        return Err(SzConfigError::AlreadyExists(format!(
41                            "Name already in hash: {name}"
42                        )));
43                    }
44
45                    // Add to hash
46                    name_hash_arr.push(json!(name));
47                } else {
48                    return Err(SzConfigError::InvalidConfig(
49                        "NAME_HASH is not an array".to_string(),
50                    ));
51                }
52            }
53        } else {
54            return Err(SzConfigError::NotFound(
55                "SYS_OOM section not found".to_string(),
56            ));
57        }
58    }
59
60    Ok(serde_json::to_string(&config_data)?)
61}
62
63/// Delete a name from the NAME_HASH array
64///
65/// # Arguments
66///
67/// * `config_json` - Configuration JSON string
68/// * `name` - Name value to remove
69///
70/// # Returns
71///
72/// Returns modified configuration JSON on success
73///
74/// # Example
75///
76/// ```
77/// use sz_configtool_lib::hashes;
78///
79/// let config = r#"{"G2_CONFIG": {"SYS_OOM": {"NAME_HASH": ["JOHN"]}}}"#;
80/// let modified = hashes::delete_from_name_hash(config, "JOHN").unwrap();
81/// ```
82pub fn delete_from_name_hash(config_json: &str, name: &str) -> Result<String> {
83    let mut config_data: Value = serde_json::from_str(config_json)?;
84    let mut found = false;
85
86    if let Some(g2_config) = config_data.get_mut("G2_CONFIG") {
87        if let Some(sys_oom) = g2_config.get_mut("SYS_OOM") {
88            if let Some(sys_oom_obj) = sys_oom.as_object_mut() {
89                if let Some(name_hash) = sys_oom_obj.get_mut("NAME_HASH") {
90                    if let Some(name_hash_arr) = name_hash.as_array_mut() {
91                        let before_len = name_hash_arr.len();
92                        name_hash_arr.retain(|v| v.as_str() != Some(name));
93                        found = name_hash_arr.len() < before_len;
94                    }
95                }
96            }
97        }
98    }
99
100    if !found {
101        return Err(SzConfigError::NotFound(format!(
102            "Name not found in hash: {name}"
103        )));
104    }
105
106    Ok(serde_json::to_string(&config_data)?)
107}
108
109/// Add a name to the SSN_LAST4_HASH array
110///
111/// # Arguments
112///
113/// * `config_json` - Configuration JSON string
114/// * `name` - Name value to add
115///
116/// # Returns
117///
118/// Returns modified configuration JSON on success
119///
120/// # Example
121///
122/// ```
123/// use sz_configtool_lib::hashes;
124///
125/// let config = r#"{"G2_CONFIG": {"SYS_OOM": {"SSN_LAST4_HASH": []}}}"#;
126/// let modified = hashes::add_to_ssn_last4_hash(config, "SMITH").unwrap();
127/// ```
128pub fn add_to_ssn_last4_hash(config_json: &str, name: &str) -> Result<String> {
129    let mut config_data: Value = serde_json::from_str(config_json)?;
130
131    if let Some(g2_config) = config_data.get_mut("G2_CONFIG") {
132        if let Some(sys_oom) = g2_config.get_mut("SYS_OOM") {
133            if let Some(sys_oom_obj) = sys_oom.as_object_mut() {
134                // Get or create SSN_LAST4_HASH array
135                let ssn_last4_hash = sys_oom_obj.entry("SSN_LAST4_HASH").or_insert(json!([]));
136
137                if let Some(ssn_last4_hash_arr) = ssn_last4_hash.as_array_mut() {
138                    // Check if already exists
139                    if ssn_last4_hash_arr.iter().any(|v| v.as_str() == Some(name)) {
140                        return Err(SzConfigError::AlreadyExists(format!(
141                            "Name already in SSN_LAST4_HASH: {name}"
142                        )));
143                    }
144
145                    // Add to hash
146                    ssn_last4_hash_arr.push(json!(name));
147                } else {
148                    return Err(SzConfigError::InvalidConfig(
149                        "SSN_LAST4_HASH is not an array".to_string(),
150                    ));
151                }
152            }
153        } else {
154            return Err(SzConfigError::NotFound(
155                "SYS_OOM section not found".to_string(),
156            ));
157        }
158    }
159
160    Ok(serde_json::to_string(&config_data)?)
161}
162
163/// Delete a name from the SSN_LAST4_HASH array
164///
165/// # Arguments
166///
167/// * `config_json` - Configuration JSON string
168/// * `name` - Name value to remove
169///
170/// # Returns
171///
172/// Returns modified configuration JSON on success
173///
174/// # Example
175///
176/// ```
177/// use sz_configtool_lib::hashes;
178///
179/// let config = r#"{"G2_CONFIG": {"SYS_OOM": {"SSN_LAST4_HASH": ["SMITH"]}}}"#;
180/// let modified = hashes::delete_from_ssn_last4_hash(config, "SMITH").unwrap();
181/// ```
182pub fn delete_from_ssn_last4_hash(config_json: &str, name: &str) -> Result<String> {
183    let mut config_data: Value = serde_json::from_str(config_json)?;
184    let mut removed = false;
185
186    if let Some(g2_config) = config_data.get_mut("G2_CONFIG") {
187        if let Some(sys_oom) = g2_config.get_mut("SYS_OOM") {
188            if let Some(sys_oom_obj) = sys_oom.as_object_mut() {
189                if let Some(ssn_last4_hash) = sys_oom_obj.get_mut("SSN_LAST4_HASH") {
190                    if let Some(ssn_last4_hash_arr) = ssn_last4_hash.as_array_mut() {
191                        // Find and remove the name
192                        if let Some(pos) = ssn_last4_hash_arr
193                            .iter()
194                            .position(|v| v.as_str() == Some(name))
195                        {
196                            ssn_last4_hash_arr.remove(pos);
197                            removed = true;
198                        }
199                    } else {
200                        return Err(SzConfigError::InvalidConfig(
201                            "SSN_LAST4_HASH is not an array".to_string(),
202                        ));
203                    }
204                } else {
205                    return Err(SzConfigError::NotFound(
206                        "SSN_LAST4_HASH not found in SYS_OOM".to_string(),
207                    ));
208                }
209            }
210        } else {
211            return Err(SzConfigError::NotFound(
212                "SYS_OOM section not found".to_string(),
213            ));
214        }
215    }
216
217    if !removed {
218        return Err(SzConfigError::NotFound(format!(
219            "Name not found in SSN_LAST4_HASH: {name}"
220        )));
221    }
222
223    Ok(serde_json::to_string(&config_data)?)
224}