hpl_toolkit/utils/
short_string.rs

1use std::io::Read;
2
3use anchor_lang::prelude::*;
4
5#[cfg(feature = "compression")]
6use crate::compression::*;
7
8#[cfg(feature = "schema")]
9use crate::schema::*;
10
11#[cfg_attr(feature = "debug", derive(Debug))]
12#[derive(Clone, Eq, PartialEq)]
13pub struct ShortString(String);
14
15impl ShortString {
16    pub fn new(string: String) -> std::io::Result<Self> {
17        if string.len() > 255 {
18            return Err(std::io::Error::new(
19                std::io::ErrorKind::InvalidInput,
20                "Short string length shall not exceed 255",
21            ));
22        }
23        Ok(Self(string))
24    }
25
26    pub fn new_unchecked(string: String) -> Self {
27        Self::new(string).expect("Short string length shall not exceed 255")
28    }
29
30    pub unsafe fn new_unsafe(string: String) -> Self {
31        Self::new_unchecked(string)
32    }
33
34    pub fn to_string(&self) -> String {
35        self.0.clone()
36    }
37
38    pub fn as_str(&self) -> &str {
39        self.0.as_str()
40    }
41}
42
43impl From<String> for ShortString {
44    fn from(value: String) -> Self {
45        Self::new_unchecked(value)
46    }
47}
48
49impl From<&String> for ShortString {
50    fn from(value: &String) -> Self {
51        Self::new_unchecked(value.to_owned())
52    }
53}
54
55impl Into<String> for ShortString {
56    fn into(self) -> String {
57        self.0
58    }
59}
60
61impl PartialEq<String> for ShortString {
62    fn eq(&self, other: &String) -> bool {
63        self.0 == *other
64    }
65}
66
67impl From<&str> for ShortString {
68    fn from(value: &str) -> Self {
69        Self::new_unchecked(value.to_string())
70    }
71}
72
73impl AnchorSerialize for ShortString {
74    fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
75        let length = self.0.len() as u8;
76        length.serialize(writer)?;
77        writer.write(self.0.as_bytes())?;
78        Ok(())
79    }
80}
81
82impl AnchorDeserialize for ShortString {
83    fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
84        let mut buf: [u8; 1] = [0; 1];
85        let limit = reader.read(&mut buf)?;
86        if limit != 1 {
87            #[cfg(feature = "log")]
88            crate::logger::debug!("limit: {}, Buf: {:?}", limit, buf);
89            return Err(std::io::Error::new(
90                std::io::ErrorKind::InvalidInput,
91                "Unexpected length of input",
92            ));
93        }
94
95        let mut string = String::new();
96        reader.take(buf[0] as u64).read_to_string(&mut string)?;
97        Ok(Self(string))
98    }
99}
100
101#[cfg(feature = "idl-build")]
102impl anchor_lang::IdlBuild for ShortString {
103    /// Returns the full module path of the type.
104    fn get_full_path() -> String {
105        format!(
106            "{0}::{1}",
107            "hpl_toolkit::utils::short_string", "ShortString",
108        )
109    }
110}
111
112#[cfg(feature = "compression")]
113impl ToNode for ShortString {
114    fn to_node(&self) -> [u8; 32] {
115        self.0.to_node()
116    }
117}
118
119#[cfg(feature = "schema")]
120impl ToSchema for ShortString {
121    fn schema() -> Schema {
122        String::schema()
123    }
124
125    fn schema_value(&self) -> SchemaValue {
126        self.0.schema_value()
127    }
128}