use super::{MaxSerializedLen, CONTENTS_FULL};
use borsh::{BorshDeserialize, BorshSerialize};
use std::convert::{From, TryFrom};
#[repr(C)]
#[derive(BorshDeserialize, BorshSerialize, Clone, Debug)]
pub struct MaxLenString<const N: usize> {
contents: String,
}
impl<const N: usize> MaxSerializedLen for MaxLenString<N> {
const MAX_SERIALIZED_LEN: usize = 4 + N;
}
impl<const N: usize> MaxLenString<N> {
pub fn contents(&self) -> &str {
self.contents.as_str()
}
pub fn contents_mut(&mut self) -> &mut str {
self.contents.as_mut_str()
}
}
impl<const N: usize> TryFrom<String> for MaxLenString<N> {
type Error = &'static str;
fn try_from(string: String) -> Result<Self, Self::Error> {
if string.as_bytes().len() > N {
return Err(CONTENTS_FULL);
}
Ok(Self { contents: string })
}
}
impl<const N: usize> TryFrom<&str> for MaxLenString<N> {
type Error = &'static str;
fn try_from(string_slice: &str) -> Result<Self, Self::Error> {
Self::try_from(string_slice.to_owned())
}
}
impl<const N: usize> From<MaxLenString<N>> for String {
fn from(rhs: MaxLenString<N>) -> Self {
rhs.contents
}
}
#[cfg(test)]
mod test_max_len_string {
use super::*;
type TestString = MaxLenString<5>;
#[test]
fn valid_conversions() {
let string_slice = "ASDEF";
let max_len_string = TestString::try_from(string_slice).unwrap();
assert_eq!(string_slice, max_len_string.contents);
let string = "ASDEF".to_string();
let max_len_string = TestString::try_from(string.clone()).unwrap();
assert_eq!(string, max_len_string.contents);
assert_eq!(string_slice, String::from(max_len_string));
}
#[test]
fn invalid_conversions() {
let string_slice = "ASDEFG";
assert!(TestString::try_from(string_slice).is_err());
let string = "ASDEFG".to_string();
assert!(TestString::try_from(string).is_err());
}
#[test]
fn max_len_string_serialized_len() {
let test_string: TestString = TestString::try_from("asd").unwrap();
assert!(test_string.try_to_vec().unwrap().len() <= TestString::MAX_SERIALIZED_LEN);
let test_string: TestString = TestString::try_from("asdef".to_string()).unwrap();
assert_eq!(
test_string.try_to_vec().unwrap().len(),
TestString::MAX_SERIALIZED_LEN
);
}
}