use base64::{Engine as _, engine::general_purpose::STANDARD};
use crate::core::validators::ValidationError;
use super::FieldType;
pub fn validate_binary_field(
value: &[u8],
max_length: Option<usize>,
) -> Result<(), ValidationError> {
if let Some(max_length) = max_length
&& value.len() > max_length
{
return Err(ValidationError::new(
"Ensure this value has at most {limit_value} bytes.",
"max_length",
)
.with_param("limit_value", max_length.to_string())
.with_param("show_value", value.len().to_string()));
}
Ok(())
}
#[must_use]
pub fn to_vec(value: &[u8]) -> Vec<u8> {
value.to_vec()
}
#[must_use]
pub fn db_type(field: &FieldType, vendor: &str) -> Option<String> {
match field {
FieldType::Binary => Some(match vendor {
"postgres" => "bytea".to_string(),
"mysql" => "longblob".to_string(),
_ => "blob".to_string(),
}),
_ => None,
}
}
pub fn get_prep_value(value: &[u8]) -> Result<String, ValidationError> {
validate_binary_field(value, None)?;
Ok(STANDARD.encode(value))
}
pub fn from_db_value(value: &str) -> Result<Vec<u8>, ValidationError> {
STANDARD.decode(value).map_err(|_| {
ValidationError::new("Enter a valid base64-encoded binary value.", "invalid")
.with_param("value", value)
})
}
#[must_use]
pub fn formfield(field: &FieldType) -> Option<&'static str> {
match field {
FieldType::Binary => None,
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::{FieldType, db_type, formfield, from_db_value, get_prep_value};
#[test]
fn db_type_for_postgres_uses_bytea() {
assert_eq!(
db_type(&FieldType::Binary, "postgres").as_deref(),
Some("bytea")
);
}
#[test]
fn get_prep_value_encodes_base64() {
let prepared = get_prep_value(b"hello").expect("binary preparation should base64 encode");
assert_eq!(prepared, "aGVsbG8=");
}
#[test]
fn from_db_value_decodes_base64() {
let parsed = from_db_value("aGVsbG8=").expect("base64 storage should decode");
assert_eq!(parsed, b"hello");
}
#[test]
fn formfield_is_not_available_for_binary() {
assert_eq!(formfield(&FieldType::Binary), None);
}
}