fidl_next_codec/wire/string/
optional.rs
1use core::fmt;
6use core::str::from_utf8;
7
8use munge::munge;
9
10use crate::{
11 Decode, DecodeError, Decoder, EncodableOption, EncodeError, EncodeOption, Encoder, Slot,
12 TakeFrom, WireOptionalVector, WireString, WireVector, ZeroPadding,
13};
14
15#[repr(transparent)]
17pub struct WireOptionalString {
18 vec: WireOptionalVector<u8>,
19}
20
21unsafe impl ZeroPadding for WireOptionalString {
22 #[inline]
23 unsafe fn zero_padding(ptr: *mut Self) {
24 unsafe {
25 WireOptionalVector::<u8>::zero_padding(ptr.cast());
26 }
27 }
28}
29
30impl WireOptionalString {
31 #[inline]
33 pub fn encode_present(slot: Slot<'_, Self>, len: u64) {
34 munge!(let Self { vec } = slot);
35 WireOptionalVector::encode_present(vec, len);
36 }
37
38 #[inline]
40 pub fn encode_absent(slot: Slot<'_, Self>) {
41 munge!(let Self { vec } = slot);
42 WireOptionalVector::encode_absent(vec);
43 }
44
45 #[inline]
47 pub fn is_some(&self) -> bool {
48 self.vec.is_some()
49 }
50
51 #[inline]
53 pub fn is_none(&self) -> bool {
54 self.vec.is_none()
55 }
56
57 #[inline]
59 pub fn as_ref(&self) -> Option<&WireString> {
60 self.vec.as_ref().map(|vec| unsafe { &*(vec as *const WireVector<u8>).cast() })
61 }
62}
63
64impl fmt::Debug for WireOptionalString {
65 #[inline]
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 self.as_ref().fmt(f)
68 }
69}
70
71unsafe impl<D: Decoder + ?Sized> Decode<D> for WireOptionalString {
72 #[inline]
73 fn decode(slot: Slot<'_, Self>, decoder: &mut D) -> Result<(), DecodeError> {
74 munge!(let Self { mut vec } = slot);
75
76 unsafe {
77 WireOptionalVector::decode_raw(vec.as_mut(), decoder)?;
78 }
79 let vec = unsafe { vec.deref_unchecked() };
80 if let Some(bytes) = vec.as_ref() {
81 if !bytes.as_slice().is_ascii() {
83 let _ = from_utf8(bytes)?;
86 }
87 }
88
89 Ok(())
90 }
91}
92
93impl EncodableOption for String {
94 type EncodedOption = WireOptionalString;
95}
96
97impl<E: Encoder + ?Sized> EncodeOption<E> for String {
98 #[inline]
99 fn encode_option(
100 this: Option<&mut Self>,
101 encoder: &mut E,
102 slot: Slot<'_, Self::EncodedOption>,
103 ) -> Result<(), EncodeError> {
104 if let Some(string) = this {
105 encoder.write(string.as_bytes());
106 WireOptionalString::encode_present(slot, string.len() as u64);
107 } else {
108 WireOptionalString::encode_absent(slot);
109 }
110
111 Ok(())
112 }
113}
114
115impl TakeFrom<WireOptionalString> for Option<String> {
116 #[inline]
117 fn take_from(from: &WireOptionalString) -> Self {
118 from.as_ref().map(String::take_from)
119 }
120}