1use crate::{
2 builder::Builder, errors::ErrorKind, slice_helpers::SliceWithStartOffset, traits::*, Cursor,
3 Offset,
4};
5use core::mem::MaybeUninit;
6
7impl WriteAsOffset<str> for str {
8 #[inline]
9 fn prepare(&self, builder: &mut Builder) -> Offset<str> {
10 let size_including_len_and_null = self.len().checked_add(5).unwrap();
11 unsafe {
13 builder.write_with(
14 size_including_len_and_null,
15 u32::ALIGNMENT_MASK,
16 |buffer_position, bytes| {
17 let bytes = bytes.as_mut_ptr();
18
19 (self.len() as u32).write(
20 Cursor::new(&mut *(bytes as *mut [MaybeUninit<u8>; 4])),
21 buffer_position,
22 );
23 core::ptr::copy_nonoverlapping(
24 self.as_bytes().as_ptr() as *const MaybeUninit<u8>,
25 bytes.add(4),
26 self.len(),
27 );
28 bytes.add(4 + self.len()).write(MaybeUninit::new(0));
29 },
30 )
31 }
32 builder.current_offset()
33 }
34}
35
36impl WriteAs<Offset<str>> for str {
37 type Prepared = Offset<str>;
38
39 #[inline]
40 fn prepare(&self, builder: &mut Builder) -> Offset<str> {
41 WriteAsOffset::prepare(self, builder)
42 }
43}
44
45impl WriteAsOptional<Offset<str>> for str {
46 type Prepared = Offset<str>;
47 #[inline]
48 fn prepare(&self, builder: &mut Builder) -> Option<Offset<str>> {
49 Some(WriteAsOffset::prepare(self, builder))
50 }
51}
52
53impl WriteAsDefault<Offset<str>, str> for str {
54 type Prepared = Offset<str>;
55
56 #[inline]
57 fn prepare(&self, builder: &mut Builder, default: &str) -> Option<Offset<str>> {
58 if self == default {
59 None
60 } else {
61 Some(WriteAsOffset::prepare(self, builder))
62 }
63 }
64}
65
66impl<'buf> TableRead<'buf> for &'buf str {
67 fn from_buffer(
68 buffer: SliceWithStartOffset<'buf>,
69 offset: usize,
70 ) -> core::result::Result<Self, ErrorKind> {
71 let (buffer, len) = super::array_from_buffer(buffer, offset)?;
72 #[cfg(feature = "extra-validation")]
73 if buffer.as_slice().get(len) != Some(&0) {
74 return Err(ErrorKind::MissingNullTerminator);
75 }
76 let slice = buffer
77 .as_slice()
78 .get(..len)
79 .ok_or(ErrorKind::InvalidLength)?;
80 Ok(core::str::from_utf8(slice)?)
81 }
82}
83
84impl<'buf> VectorReadInner<'buf> for &'buf str {
85 type Error = crate::errors::Error;
86
87 const STRIDE: usize = 4;
88 #[inline]
89 unsafe fn from_buffer(
90 buffer: SliceWithStartOffset<'buf>,
91 offset: usize,
92 ) -> crate::Result<&'buf str> {
93 let add_context =
94 |e: ErrorKind| e.with_error_location("[str]", "get", buffer.offset_from_start);
95 let (slice, len) = super::array_from_buffer(buffer, offset).map_err(add_context)?;
96 #[cfg(feature = "extra-validation")]
97 if slice.as_slice().get(len) != Some(&0) {
98 return Err(add_context(ErrorKind::MissingNullTerminator));
99 }
100 let slice = slice
101 .as_slice()
102 .get(..len)
103 .ok_or(ErrorKind::InvalidLength)
104 .map_err(add_context)?;
105 let str = core::str::from_utf8(slice)
106 .map_err(|source| ErrorKind::InvalidUtf8 { source })
107 .map_err(add_context)?;
108 Ok(str)
109 }
110}
111
112impl VectorWrite<Offset<str>> for str {
113 type Value = Offset<str>;
114
115 const STRIDE: usize = 4;
116 #[inline]
117 fn prepare(&self, builder: &mut Builder) -> Self::Value {
118 WriteAs::prepare(self, builder)
119 }
120
121 #[inline]
122 unsafe fn write_values(
123 values: &[Offset<str>],
124 bytes: *mut MaybeUninit<u8>,
125 buffer_position: u32,
126 ) {
127 let bytes = bytes as *mut [MaybeUninit<u8>; 4];
128 for (i, v) in values.iter().enumerate() {
129 v.write(
130 Cursor::new(&mut *bytes.add(i)),
131 buffer_position - (4 * i) as u32,
132 );
133 }
134 }
135}