toe_beans/v4/message/
sname.rs1use crate::v4::error::Result;
2use std::{
3 cmp::Ordering,
4 ffi::{CStr, CString},
5};
6
7#[derive(Debug, PartialEq)]
17pub struct SName([u8; 64]);
18
19impl SName {
20 pub fn new(name: &CStr) -> Result<Self> {
23 let bytes = name.to_bytes_with_nul();
24 match bytes.len().cmp(&64) {
25 Ordering::Less => {
26 let mut padding = [0u8; 64];
27 bytes
28 .iter()
29 .enumerate()
30 .for_each(|(i, byte)| padding[i] = *byte);
31 Ok(Self(padding))
32 }
33 Ordering::Equal => Ok(Self(bytes.try_into().unwrap())),
34 Ordering::Greater => Err("SName does not fit in a 64 byte array"),
35 }
36 }
37
38 pub fn from_slice_unchecked(name: &[u8]) -> Self {
45 Self(name.try_into().unwrap())
46 }
47
48 pub fn from_array(name: [u8; 64]) -> Self {
50 Self(name)
51 }
52
53 pub const EMPTY: Self = Self([0; 64]);
57
58 pub fn to_string(&self) -> CString {
61 CStr::from_bytes_until_nul(&self.0).unwrap().to_owned()
62 }
63
64 pub fn len(&self) -> usize {
70 64
71 }
72}
73
74impl From<&SName> for [u8; 64] {
75 fn from(sname: &SName) -> Self {
76 sname.0
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn test_new_sname_below_length() {
86 let sname = SName::new(c"12345");
87 assert!(sname.is_ok());
88 }
89
90 #[test]
91 fn test_new_sname_at_length() {
92 let sname = SName::new(c"123451234512345123451234512345123451234512345123451234512345123");
94 assert!(sname.is_ok());
95 }
96
97 #[test]
98 fn test_new_sname_above_length() {
99 let sname = SName::new(c"1234512345123451234512345123451234512345123451234512345123451234512345123451234512345123451234512345123451234512345123451234512345");
100 assert!(sname.is_err());
101 }
102
103 #[test]
104 fn test_empty() {
105 let sname = SName::EMPTY;
106 assert_eq!(sname.0, [0; 64]);
107 }
108}