agsol_common/
max_len_string.rs1use super::{MaxSerializedLen, CONTENTS_FULL};
2
3use borsh::{BorshDeserialize, BorshSerialize};
4
5use std::convert::{From, TryFrom};
6
7#[repr(C)]
8#[derive(BorshDeserialize, BorshSerialize, Clone, Debug)]
9pub struct MaxLenString<const N: usize> {
10 contents: String,
11}
12
13impl<const N: usize> MaxSerializedLen for MaxLenString<N> {
14 const MAX_SERIALIZED_LEN: usize = 4 + N;
15}
16
17impl<const N: usize> MaxLenString<N> {
18 pub fn contents(&self) -> &str {
19 self.contents.as_str()
20 }
21
22 pub fn contents_mut(&mut self) -> &mut str {
23 self.contents.as_mut_str()
24 }
25}
26
27impl<const N: usize> TryFrom<String> for MaxLenString<N> {
28 type Error = &'static str;
29
30 fn try_from(string: String) -> Result<Self, Self::Error> {
31 if string.as_bytes().len() > N {
32 return Err(CONTENTS_FULL);
33 }
34 Ok(Self { contents: string })
35 }
36}
37
38impl<const N: usize> TryFrom<&str> for MaxLenString<N> {
39 type Error = &'static str;
40
41 fn try_from(string_slice: &str) -> Result<Self, Self::Error> {
42 Self::try_from(string_slice.to_owned())
43 }
44}
45
46impl<const N: usize> From<MaxLenString<N>> for String {
47 fn from(rhs: MaxLenString<N>) -> Self {
48 rhs.contents
49 }
50}
51
52#[cfg(test)]
53mod test_max_len_string {
54 use super::*;
55
56 type TestString = MaxLenString<5>;
57
58 #[test]
59 fn valid_conversions() {
60 let string_slice = "ASDEF";
61 let max_len_string = TestString::try_from(string_slice).unwrap();
62 assert_eq!(string_slice, max_len_string.contents);
63
64 let string = "ASDEF".to_string();
65 let max_len_string = TestString::try_from(string.clone()).unwrap();
66 assert_eq!(string, max_len_string.contents);
67
68 assert_eq!(string_slice, String::from(max_len_string));
69 }
70
71 #[test]
72 fn invalid_conversions() {
73 let string_slice = "ASDEFG";
74 assert!(TestString::try_from(string_slice).is_err());
75
76 let string = "ASDEFG".to_string();
77 assert!(TestString::try_from(string).is_err());
78 }
79
80 #[test]
81 fn max_len_string_serialized_len() {
82 let test_string: TestString = TestString::try_from("asd").unwrap();
83 assert!(test_string.try_to_vec().unwrap().len() <= TestString::MAX_SERIALIZED_LEN);
84
85 let test_string: TestString = TestString::try_from("asdef".to_string()).unwrap();
86 assert_eq!(
87 test_string.try_to_vec().unwrap().len(),
88 TestString::MAX_SERIALIZED_LEN
89 );
90 }
91}