use crate::v4::error::Result;
use std::{
cmp::Ordering,
ffi::{CStr, CString},
};
#[derive(Debug, PartialEq)]
pub struct SName([u8; 64]);
impl SName {
pub fn new(name: &CStr) -> Result<Self> {
let bytes = name.to_bytes_with_nul();
match bytes.len().cmp(&64) {
Ordering::Less => {
let mut padding = [0u8; 64];
bytes
.iter()
.enumerate()
.for_each(|(i, byte)| padding[i] = *byte);
Ok(Self(padding))
}
Ordering::Equal => Ok(Self(bytes.try_into().unwrap())),
Ordering::Greater => Err("SName does not fit in a 64 byte array"),
}
}
pub fn from_slice_unchecked(name: &[u8]) -> Self {
Self(name.try_into().unwrap())
}
pub fn from_array(name: [u8; 64]) -> Self {
Self(name)
}
pub const EMPTY: Self = Self([0; 64]);
pub fn to_string(&self) -> CString {
CStr::from_bytes_until_nul(&self.0).unwrap().to_owned()
}
pub fn len(&self) -> usize {
64
}
}
impl From<&SName> for [u8; 64] {
fn from(sname: &SName) -> Self {
sname.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_sname_below_length() {
let sname = SName::new(c"12345");
assert!(sname.is_ok());
}
#[test]
fn test_new_sname_at_length() {
let sname = SName::new(c"123451234512345123451234512345123451234512345123451234512345123");
assert!(sname.is_ok());
}
#[test]
fn test_new_sname_above_length() {
let sname = SName::new(c"1234512345123451234512345123451234512345123451234512345123451234512345123451234512345123451234512345123451234512345123451234512345");
assert!(sname.is_err());
}
#[test]
fn test_empty() {
let sname = SName::EMPTY;
assert_eq!(sname.0, [0; 64]);
}
}