fidl_next_codec/wire/string/
required.rs1use core::fmt;
6use core::mem::MaybeUninit;
7use core::ops::Deref;
8use core::str::{from_utf8, from_utf8_unchecked};
9
10use munge::munge;
11
12use crate::{
13 Constrained, Decode, DecodeError, Decoder, Encodable, Encode, EncodeError, EncodeRef, Encoder,
14 FromWire, FromWireRef, IntoNatural, Slot, ValidationError, Wire, WireVector,
15};
16
17#[repr(transparent)]
19pub struct WireString<'de> {
20 vec: WireVector<'de, u8>,
21}
22
23unsafe impl Wire for WireString<'static> {
24 type Decoded<'de> = WireString<'de>;
25
26 #[inline]
27 fn zero_padding(out: &mut MaybeUninit<Self>) {
28 munge!(let Self { vec } = out);
29 WireVector::<u8>::zero_padding(vec);
30 }
31}
32
33impl WireString<'_> {
34 #[inline]
36 pub fn encode_present(out: &mut MaybeUninit<Self>, len: u64) {
37 munge!(let Self { vec } = out);
38 WireVector::encode_present(vec, len);
39 }
40
41 #[inline]
43 pub fn len(&self) -> usize {
44 self.vec.len()
45 }
46
47 #[inline]
49 pub fn is_empty(&self) -> bool {
50 self.len() == 0
51 }
52
53 #[inline]
55 pub fn as_str(&self) -> &str {
56 unsafe { from_utf8_unchecked(self.vec.as_slice()) }
57 }
58
59 fn validate_max_len(slot: Slot<'_, Self>, limit: u64) -> Result<(), crate::ValidationError> {
61 munge!(let Self { vec } = slot);
62 match WireVector::validate_max_len(vec, limit) {
63 Ok(()) => Ok(()),
64 Err(ValidationError::VectorTooLong { count, limit }) => {
65 Err(ValidationError::StringTooLong { count, limit })
66 }
67 Err(e) => Err(e),
68 }
69 }
70}
71
72impl Constrained for WireString<'_> {
73 type Constraint = u64;
74
75 fn validate(slot: Slot<'_, Self>, constraint: u64) -> Result<(), ValidationError> {
76 Self::validate_max_len(slot, constraint)
77 }
78}
79
80impl Deref for WireString<'_> {
81 type Target = str;
82
83 #[inline]
84 fn deref(&self) -> &Self::Target {
85 self.as_str()
86 }
87}
88
89impl fmt::Debug for WireString<'_> {
90 #[inline]
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 self.as_str().fmt(f)
93 }
94}
95
96unsafe impl<D: Decoder + ?Sized> Decode<D> for WireString<'static> {
97 #[inline]
98 fn decode(slot: Slot<'_, Self>, decoder: &mut D, constraint: u64) -> Result<(), DecodeError> {
99 munge!(let Self { mut vec } = slot);
100
101 match unsafe { WireVector::decode_raw(vec.as_mut(), decoder, constraint) } {
102 Ok(()) => (),
103 Err(DecodeError::Validation(ValidationError::VectorTooLong { count, limit })) => {
104 return Err(DecodeError::Validation(ValidationError::StringTooLong {
105 count,
106 limit,
107 }));
108 }
109 Err(e) => {
110 return Err(e);
111 }
112 };
113 let vec = unsafe { vec.deref_unchecked() };
114
115 if !vec.as_slice().is_ascii() {
117 let _ = from_utf8(vec.as_slice())?;
120 }
121
122 Ok(())
123 }
124}
125
126impl Encodable for String {
127 type Encoded = WireString<'static>;
128}
129
130unsafe impl<E: Encoder + ?Sized> Encode<E> for String {
131 #[inline]
132 fn encode(
133 self,
134 encoder: &mut E,
135 out: &mut MaybeUninit<Self::Encoded>,
136 constraint: u64,
137 ) -> Result<(), EncodeError> {
138 self.as_str().encode(encoder, out, constraint)
139 }
140}
141
142unsafe impl<E: Encoder + ?Sized> EncodeRef<E> for String {
143 #[inline]
144 fn encode_ref(
145 &self,
146 encoder: &mut E,
147 out: &mut MaybeUninit<Self::Encoded>,
148 constraint: u64,
149 ) -> Result<(), EncodeError> {
150 self.as_str().encode(encoder, out, constraint)
151 }
152}
153
154impl Encodable for &str {
155 type Encoded = WireString<'static>;
156}
157
158unsafe impl<E: Encoder + ?Sized> Encode<E> for &str {
159 #[inline]
160 fn encode(
161 self,
162 encoder: &mut E,
163 out: &mut MaybeUninit<Self::Encoded>,
164 _constraint: u64,
165 ) -> Result<(), EncodeError> {
166 encoder.write(self.as_bytes());
167 WireString::encode_present(out, self.len() as u64);
168 Ok(())
169 }
170}
171
172impl FromWire<WireString<'_>> for String {
173 #[inline]
174 fn from_wire(wire: WireString<'_>) -> Self {
175 String::from_wire_ref(&wire)
176 }
177}
178
179impl IntoNatural for WireString<'_> {
180 type Natural = String;
181}
182
183impl FromWireRef<WireString<'_>> for String {
184 #[inline]
185 fn from_wire_ref(wire: &WireString<'_>) -> Self {
186 unsafe { String::from_utf8_unchecked(Vec::from_wire_ref(&wire.vec)) }
187 }
188}