fidl_next_codec/wire/string/
required.rs
1use core::fmt;
6use core::ops::Deref;
7use core::str::{from_utf8, from_utf8_unchecked};
8
9use munge::munge;
10
11use crate::{
12 Decode, DecodeError, Decoder, Encodable, Encode, EncodeError, Encoder, Slot, TakeFrom,
13 WireVector, ZeroPadding,
14};
15
16#[repr(transparent)]
18pub struct WireString {
19 vec: WireVector<u8>,
20}
21
22unsafe impl ZeroPadding for WireString {
23 #[inline]
24 unsafe fn zero_padding(ptr: *mut Self) {
25 unsafe {
26 WireVector::<u8>::zero_padding(ptr.cast());
27 }
28 }
29}
30
31impl WireString {
32 #[inline]
34 pub fn encode_present(slot: Slot<'_, Self>, len: u64) {
35 munge!(let Self { vec } = slot);
36 WireVector::encode_present(vec, len);
37 }
38
39 #[inline]
41 pub fn len(&self) -> usize {
42 self.vec.len()
43 }
44
45 #[inline]
47 pub fn is_empty(&self) -> bool {
48 self.len() == 0
49 }
50
51 #[inline]
53 pub fn as_str(&self) -> &str {
54 unsafe { from_utf8_unchecked(self.vec.as_slice()) }
55 }
56}
57
58impl Deref for WireString {
59 type Target = str;
60
61 #[inline]
62 fn deref(&self) -> &Self::Target {
63 self.as_str()
64 }
65}
66
67impl fmt::Debug for WireString {
68 #[inline]
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 self.as_str().fmt(f)
71 }
72}
73
74unsafe impl<D: Decoder + ?Sized> Decode<D> for WireString {
75 #[inline]
76 fn decode(slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
77 munge!(let Self { mut vec } = slot);
78
79 unsafe {
80 WireVector::decode_raw(vec.as_mut(), decoder)?;
81 }
82 let vec = unsafe { vec.deref_unchecked() };
83
84 if !vec.as_slice().is_ascii() {
86 let _ = from_utf8(vec.as_slice())?;
89 }
90
91 Ok(())
92 }
93}
94
95impl Encodable for String {
96 type Encoded = WireString;
97}
98
99impl<E: Encoder + ?Sized> Encode<E> for String {
100 #[inline]
101 fn encode(
102 &mut self,
103 encoder: &mut E,
104 slot: Slot<'_, Self::Encoded>,
105 ) -> Result<(), EncodeError> {
106 encoder.write(self.as_bytes());
107 WireString::encode_present(slot, self.len() as u64);
108 Ok(())
109 }
110}
111
112impl TakeFrom<WireString> for String {
113 #[inline]
114 fn take_from(from: &WireString) -> Self {
115 from.to_string()
116 }
117}