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
136
137
138
/*!
# Trim in-place

This crate is used for extending `String` in order to do in-place trimming.

## Usage

```rust
use trim_in_place::TrimInPlace;

let mut s = String::from(" 1234 abcd  ");

s.trim_in_place();

assert_eq!("1234 abcd", s);
```

## Benchmark

```bash
cargo bench
```
*/

#![no_std]

extern crate alloc;

use core::intrinsics::copy;

use alloc::string::String;

pub trait TrimInPlace {
    fn trim_in_place(&mut self) -> &str;
    fn trim_start_in_place(&mut self) -> &str;
    fn trim_end_in_place(&mut self) -> &str;

    // TODO trim_matches with Pattern
    fn trim_matches_in_place(&mut self, pat: char) -> &str;
    fn trim_start_matches_in_place(&mut self, pat: char) -> &str;
    fn trim_end_matches_in_place(&mut self, pat: char) -> &str;
}

impl TrimInPlace for String {
    #[inline]
    fn trim_in_place(&mut self) -> &str {
        let trimmed_str = self.trim();

        let trimmed_str_start_pointer = trimmed_str.as_ptr();
        let trimmed_str_length = trimmed_str.len();

        unsafe {
            let v = self.as_mut_vec();

            copy(trimmed_str_start_pointer, v.as_mut_ptr(), trimmed_str_length);

            v.set_len(trimmed_str_length);
        }

        self.as_str()
    }

    #[inline]
    fn trim_start_in_place(&mut self) -> &str {
        let trimmed_str = self.trim_start();

        let trimmed_str_start_pointer = trimmed_str.as_ptr();
        let trimmed_str_length = trimmed_str.len();

        unsafe {
            let v = self.as_mut_vec();

            copy(trimmed_str_start_pointer, v.as_mut_ptr(), trimmed_str_length);

            v.set_len(trimmed_str_length);
        }

        self.as_str()
    }

    #[inline]
    fn trim_end_in_place(&mut self) -> &str {
        let trimmed_str_length = self.trim_end().len();

        unsafe {
            self.as_mut_vec().set_len(trimmed_str_length);
        }

        self.as_str()
    }

    #[inline]
    fn trim_matches_in_place(&mut self, pat: char) -> &str {
        let trimmed_str = self.trim_matches(pat);

        let trimmed_str_start_pointer = trimmed_str.as_ptr();
        let trimmed_str_length = trimmed_str.len();

        unsafe {
            let v = self.as_mut_vec();

            copy(trimmed_str_start_pointer, v.as_mut_ptr(), trimmed_str_length);

            v.set_len(trimmed_str_length);
        }

        self.as_str()
    }

    #[inline]
    fn trim_start_matches_in_place(&mut self, pat: char) -> &str {
        let trimmed_str = self.trim_start_matches(pat);

        let trimmed_str_start_pointer = trimmed_str.as_ptr();
        let trimmed_str_length = trimmed_str.len();

        unsafe {
            let v = self.as_mut_vec();

            copy(trimmed_str_start_pointer, v.as_mut_ptr(), trimmed_str_length);

            v.set_len(trimmed_str_length);
        }

        self.as_str()
    }

    #[inline]
    fn trim_end_matches_in_place(&mut self, pat: char) -> &str {
        let trimmed_str_length = self.trim_end_matches(pat).len();

        unsafe {
            self.as_mut_vec().set_len(trimmed_str_length);
        }

        self.as_str()
    }
}