Skip to main content

multiversx_sc_codec/impl_for_types/
impl_string.rs

1use crate::{
2    DecodeError, DecodeErrorHandler, EncodeErrorHandler, NestedDecode, NestedDecodeInput,
3    NestedEncode, NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput,
4};
5use alloc::{boxed::Box, string::String, vec::Vec};
6
7impl TopEncode for String {
8    #[inline]
9    fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
10    where
11        O: TopEncodeOutput,
12        H: EncodeErrorHandler,
13    {
14        self.as_bytes().top_encode_or_handle_err(output, h)
15    }
16}
17
18impl TopEncode for &str {
19    #[inline]
20    fn top_encode_or_handle_err<O, H>(&self, output: O, _h: H) -> Result<(), H::HandledErr>
21    where
22        O: TopEncodeOutput,
23        H: EncodeErrorHandler,
24    {
25        output.set_slice_u8(self.as_bytes());
26        Ok(())
27    }
28}
29
30impl TopEncode for Box<str> {
31    #[inline]
32    fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
33    where
34        O: TopEncodeOutput,
35        H: EncodeErrorHandler,
36    {
37        self.as_ref().as_bytes().top_encode_or_handle_err(output, h)
38    }
39}
40
41impl TopDecode for String {
42    fn top_decode_or_handle_err<I, H>(input: I, h: H) -> Result<Self, H::HandledErr>
43    where
44        I: TopDecodeInput,
45        H: DecodeErrorHandler,
46    {
47        let raw = Vec::<u8>::top_decode_or_handle_err(input, h)?;
48        match String::from_utf8(raw) {
49            Ok(s) => Ok(s),
50            Err(_) => Err(h.handle_error(DecodeError::UTF8_DECODE_ERROR)),
51        }
52    }
53}
54
55impl TopDecode for Box<str> {
56    #[inline]
57    fn top_decode_or_handle_err<I, H>(input: I, h: H) -> Result<Self, H::HandledErr>
58    where
59        I: TopDecodeInput,
60        H: DecodeErrorHandler,
61    {
62        Ok(String::top_decode_or_handle_err(input, h)?.into_boxed_str())
63    }
64}
65
66impl NestedEncode for String {
67    #[inline]
68    fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
69    where
70        O: NestedEncodeOutput,
71        H: EncodeErrorHandler,
72    {
73        self.as_bytes().dep_encode_or_handle_err(dest, h)
74    }
75}
76
77impl NestedEncode for &str {
78    #[inline]
79    fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
80    where
81        O: NestedEncodeOutput,
82        H: EncodeErrorHandler,
83    {
84        self.as_bytes().dep_encode_or_handle_err(dest, h)
85    }
86}
87
88impl NestedEncode for Box<str> {
89    #[inline]
90    fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
91    where
92        O: NestedEncodeOutput,
93        H: EncodeErrorHandler,
94    {
95        self.as_ref().as_bytes().dep_encode_or_handle_err(dest, h)
96    }
97}
98
99impl NestedDecode for String {
100    fn dep_decode_or_handle_err<I, H>(input: &mut I, h: H) -> Result<Self, H::HandledErr>
101    where
102        I: NestedDecodeInput,
103        H: DecodeErrorHandler,
104    {
105        let raw = Vec::<u8>::dep_decode_or_handle_err(input, h)?;
106        match String::from_utf8(raw) {
107            Ok(s) => Ok(s),
108            Err(_) => Err(h.handle_error(DecodeError::UTF8_DECODE_ERROR)),
109        }
110    }
111}
112
113impl NestedDecode for Box<str> {
114    #[inline]
115    fn dep_decode_or_handle_err<I, H>(input: &mut I, h: H) -> Result<Self, H::HandledErr>
116    where
117        I: NestedDecodeInput,
118        H: DecodeErrorHandler,
119    {
120        Ok(String::dep_decode_or_handle_err(input, h)?.into_boxed_str())
121    }
122}
123
124#[cfg(test)]
125mod tests {
126    use crate::{
127        DecodeError, TopDecode,
128        test_util::{
129            check_dep_encode, check_dep_encode_decode, check_top_encode, check_top_encode_decode,
130        },
131    };
132    use alloc::string::String;
133
134    #[test]
135    fn test_top() {
136        let s = "abc";
137        check_top_encode_decode(String::from(s), b"abc");
138        check_top_encode_decode(String::from(s).into_boxed_str(), b"abc");
139    }
140
141    #[test]
142    fn test_dep() {
143        let s = "abc";
144        check_dep_encode_decode(String::from(s), &[0, 0, 0, 3, b'a', b'b', b'c']);
145        check_dep_encode_decode(
146            String::from(s).into_boxed_str(),
147            &[0, 0, 0, 3, b'a', b'b', b'c'],
148        );
149    }
150
151    #[test]
152    fn test_top_empty() {
153        check_top_encode_decode(String::new(), &[]);
154        check_top_encode_decode(String::new().into_boxed_str(), &[]);
155    }
156
157    #[test]
158    fn test_dep_empty() {
159        check_dep_encode_decode(String::new(), &[0, 0, 0, 0]);
160        check_dep_encode_decode(String::new().into_boxed_str(), &[0, 0, 0, 0]);
161    }
162
163    #[test]
164    fn test_top_encode_str_ref() {
165        let bytes = check_top_encode(&"hello");
166        assert_eq!(bytes, b"hello");
167    }
168
169    #[test]
170    fn test_dep_encode_str_ref() {
171        let bytes = check_dep_encode(&"hello");
172        assert_eq!(bytes, &[0, 0, 0, 5, b'h', b'e', b'l', b'l', b'o']);
173    }
174
175    #[test]
176    fn test_top_decode_invalid_utf8() {
177        // 0xFF is not valid UTF-8
178        assert_eq!(
179            String::top_decode(&[0xFFu8][..]),
180            Err(DecodeError::UTF8_DECODE_ERROR),
181        );
182    }
183}