dyn_list/
str.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use core::alloc::{AllocError, Allocator, Layout};

use crate::{
    node::{AllocateError, Header, Node},
    DynList, Ends, MaybeUninitNode,
};

impl<A> DynList<str, A>
where
    A: Allocator,
{
    /// Converts the list of byte slices to a list of string slices without checking that the slices contain valid UTF-8.
    ///
    /// # Safety
    /// All byte slices in the list must be valid UTF-8.
    /// For more information, see [`str::from_utf8_unchecked`](core::str::from_utf8_unchecked).
    pub unsafe fn from_utf8_unchecked(bytes: DynList<[u8], A>) -> Self {
        let (ends, allocator) = bytes.into_raw_parts();
        unsafe { Self::from_raw_parts(ends, allocator) }
    }

    /// Converts the list of string slices to a list of byte slices.
    pub fn into_bytes(self) -> DynList<[u8], A> {
        let (ends, allocator) = self.into_raw_parts();
        unsafe { DynList::from_raw_parts(ends, allocator) }
    }

    #[inline]
    fn try_allocate_uninit_str_front_internal(
        &mut self,
        length: usize,
    ) -> Result<MaybeUninitNode<str, A>, AllocateError> {
        let value_layout = Layout::array::<u8>(length)?;

        let header = Header {
            next: self
                .ends
                .map(|Ends { front, .. }| unsafe { front.to_transparent() }),
            previous: None,
            metadata: length,
        };

        unsafe { Node::try_new_uninit(self, value_layout, header) }
    }

    #[inline]
    fn try_allocate_uninit_str_back_internal(
        &mut self,
        length: usize,
    ) -> Result<MaybeUninitNode<str, A>, AllocateError> {
        let value_layout = Layout::array::<u8>(length)?;

        let header = Header {
            next: None,
            previous: self
                .ends
                .map(|Ends { back, .. }| unsafe { back.to_transparent() }),
            metadata: length,
        };

        unsafe { Node::try_new_uninit(self, value_layout, header) }
    }

    /// Attempts to allocate an uninitialised str node at the front of the list.
    ///
    /// # Errors
    /// If allocation fails, or an arithmetic overflow occours in [`Layout::array`], this will return an [`AllocError`].
    pub fn try_allocate_uninit_str_front(
        &mut self,
        length: usize,
    ) -> Result<MaybeUninitNode<str, A>, AllocError> {
        self.try_allocate_uninit_str_front_internal(length)
            .map_err(Into::into)
    }

    /// Attempts to allocate an uninitialised str node at the back of the list.
    ///
    /// # Errors
    /// If allocation fails, or an arithmetic overflow occours in [`Layout::array`], this will return an [`AllocError`].
    pub fn try_allocate_uninit_str_back(
        &mut self,
        length: usize,
    ) -> Result<MaybeUninitNode<str, A>, AllocError> {
        self.try_allocate_uninit_str_back_internal(length)
            .map_err(Into::into)
    }

    #[must_use]
    /// Allocates an uninitialised str node at the front of the list.
    pub fn allocate_uninit_str_front(&mut self, length: usize) -> MaybeUninitNode<str, A> {
        AllocateError::unwrap_alloc(self.try_allocate_uninit_str_front_internal(length))
    }

    #[must_use]
    /// Allocates an uninitialised str node at the back of the list.
    pub fn allocate_uninit_str_back(&mut self, length: usize) -> MaybeUninitNode<str, A> {
        AllocateError::unwrap_alloc(self.try_allocate_uninit_str_back_internal(length))
    }

    /// Attempts to copy the string slice `src` and push it to the front of the list.
    ///
    /// # Errors
    /// If allocation fails, this will return an [`AllocError`].
    pub fn try_push_front_copy_str(&mut self, src: &str) -> Result<(), AllocError> {
        let mut node = self.try_allocate_uninit_str_front(src.len())?;
        node.copy_from_str(src);
        unsafe { node.insert() };
        Ok(())
    }

    /// Attempts to copy the string slice `src` and push it to the back of the list.
    ///
    /// # Errors
    /// If allocation fails, this will return an [`AllocError`].
    pub fn try_push_back_copy_str(&mut self, src: &str) -> Result<(), AllocError> {
        let mut node = self.try_allocate_uninit_str_back(src.len())?;
        node.copy_from_str(src);
        unsafe { node.insert() };
        Ok(())
    }

    /// Copies the string slice `src` and pushes it to the front of the list.
    pub fn push_front_copy_str(&mut self, src: &str) {
        let mut node = self.allocate_uninit_str_front(src.len());
        node.copy_from_str(src);
        unsafe { node.insert() };
    }

    /// Copies the string slice `src` and pushes it to the back of the list.
    pub fn push_back_copy_str(&mut self, src: &str) {
        let mut node = self.allocate_uninit_str_back(src.len());
        node.copy_from_str(src);
        unsafe { node.insert() };
    }
}