planus/impls/
str.rs

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        // SAFETY: We make sure to write the 4+len+1 bytes inside the closure.
12        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}