fidl_next_codec/wire/string/
required.rs
1use 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 Decode, DecodeError, Decoder, Encodable, Encode, EncodeError, EncodeRef, Encoder, FromWire,
14 FromWireRef, Slot, 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
60impl Deref for WireString<'_> {
61 type Target = str;
62
63 #[inline]
64 fn deref(&self) -> &Self::Target {
65 self.as_str()
66 }
67}
68
69impl fmt::Debug for WireString<'_> {
70 #[inline]
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 self.as_str().fmt(f)
73 }
74}
75
76unsafe impl<D: Decoder + ?Sized> Decode<D> for WireString<'static> {
77 #[inline]
78 fn decode(slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
79 munge!(let Self { mut vec } = slot);
80
81 unsafe {
82 WireVector::decode_raw(vec.as_mut(), decoder)?;
83 }
84 let vec = unsafe { vec.deref_unchecked() };
85
86 if !vec.as_slice().is_ascii() {
88 let _ = from_utf8(vec.as_slice())?;
91 }
92
93 Ok(())
94 }
95}
96
97impl Encodable for String {
98 type Encoded = WireString<'static>;
99}
100
101unsafe impl<E: Encoder + ?Sized> Encode<E> for String {
102 #[inline]
103 fn encode(
104 self,
105 encoder: &mut E,
106 out: &mut MaybeUninit<Self::Encoded>,
107 ) -> Result<(), EncodeError> {
108 self.as_str().encode(encoder, out)
109 }
110}
111
112unsafe impl<E: Encoder + ?Sized> EncodeRef<E> for String {
113 #[inline]
114 fn encode_ref(
115 &self,
116 encoder: &mut E,
117 out: &mut MaybeUninit<Self::Encoded>,
118 ) -> Result<(), EncodeError> {
119 self.as_str().encode(encoder, out)
120 }
121}
122
123impl Encodable for &str {
124 type Encoded = WireString<'static>;
125}
126
127unsafe impl<E: Encoder + ?Sized> Encode<E> for &str {
128 #[inline]
129 fn encode(
130 self,
131 encoder: &mut E,
132 out: &mut MaybeUninit<Self::Encoded>,
133 ) -> Result<(), EncodeError> {
134 encoder.write(self.as_bytes());
135 WireString::encode_present(out, self.len() as u64);
136 Ok(())
137 }
138}
139
140impl FromWire<WireString<'_>> for String {
141 #[inline]
142 fn from_wire(wire: WireString<'_>) -> Self {
143 String::from_wire_ref(&wire)
144 }
145}
146
147impl FromWireRef<WireString<'_>> for String {
148 #[inline]
149 fn from_wire_ref(wire: &WireString<'_>) -> Self {
150 unsafe { String::from_utf8_unchecked(Vec::from_wire_ref(&wire.vec)) }
151 }
152}