use super::swift_utils::parse_amount;
use crate::errors::ParseError;
use crate::traits::SwiftField;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))]
pub struct Field36 {
pub rate: f64,
}
impl SwiftField for Field36 {
fn parse(input: &str) -> crate::Result<Self>
where
Self: Sized,
{
if input.is_empty() {
return Err(ParseError::InvalidFormat {
message: "Field 36 exchange rate cannot be empty".to_string(),
});
}
if input.len() > 12 {
return Err(ParseError::InvalidFormat {
message: format!(
"Field 36 must not exceed 12 characters, found {}",
input.len()
),
});
}
let rate = parse_amount(input)?;
if rate <= 0.0 {
return Err(ParseError::InvalidFormat {
message: "Field 36 exchange rate must be greater than zero".to_string(),
});
}
if !(0.0001..=100000.0).contains(&rate) {
return Err(ParseError::InvalidFormat {
message: format!(
"Field 36 exchange rate {} appears to be outside reasonable range",
rate
),
});
}
Ok(Field36 { rate })
}
fn to_swift_string(&self) -> String {
format!(":36:{}", self.rate.to_string().replace('.', ","))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_field36_valid() {
let field = Field36::parse("1,2500").unwrap();
assert_eq!(field.rate, 1.25);
assert_eq!(field.to_swift_string(), ":36:1,25");
let field = Field36::parse("0,8500").unwrap();
assert_eq!(field.rate, 0.85);
let field = Field36::parse("110,2500").unwrap();
assert_eq!(field.rate, 110.25);
let field = Field36::parse("1").unwrap();
assert_eq!(field.rate, 1.0);
let field = Field36::parse("0,0001").unwrap();
assert_eq!(field.rate, 0.0001);
let field = Field36::parse("99999").unwrap();
assert_eq!(field.rate, 99999.0);
}
#[test]
fn test_field36_invalid() {
assert!(Field36::parse("").is_err());
assert!(Field36::parse("1234567890123").is_err());
assert!(Field36::parse("0").is_err());
assert!(Field36::parse("0,00").is_err());
assert!(Field36::parse("-1,25").is_err());
assert!(Field36::parse("0,00001").is_err());
assert!(Field36::parse("999999").is_err());
}
}