rust_rcs_core/util/
raw_string.rs

1// Copyright 2023 宋昊文
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::{str::FromStr, u8};
16
17pub trait StrEq {
18    fn equals_bytes(&self, b: &[u8], ignore_case: bool) -> bool;
19    fn equals_string(&self, s: &str, ignore_case: bool) -> bool;
20}
21
22impl StrEq for [u8] {
23    fn equals_bytes(&self, b: &[u8], ignore_case: bool) -> bool {
24        if self.len() != b.len() {
25            return false;
26        }
27
28        let mut i = 0;
29        let mut rh_iter = b.iter();
30        loop {
31            if let Some(rhs) = rh_iter.next() {
32                let lhs = self[i];
33                if lhs == *rhs {
34                    i = i + 1;
35                    continue;
36                }
37                if ignore_case {
38                    if lhs >= b'a' && lhs <= b'z' && *rhs == (lhs + b'A' - b'a')
39                        || lhs >= b'A' && lhs <= b'Z' && *rhs == (lhs - b'A' + b'a')
40                    {
41                        i = i + 1;
42                        continue;
43                    }
44                }
45                return false;
46            } else {
47                return true;
48            }
49        }
50    }
51
52    fn equals_string(&self, s: &str, ignore_case: bool) -> bool {
53        let b = s.as_bytes();
54        <[u8]>::equals_bytes(self, b, ignore_case)
55    }
56}
57
58impl StrEq for Vec<u8> {
59    fn equals_bytes(&self, b: &[u8], ignore_case: bool) -> bool {
60        <[u8]>::equals_bytes(self, b, ignore_case)
61    }
62
63    fn equals_string(&self, s: &str, ignore_case: bool) -> bool {
64        <[u8]>::equals_string(self, s, ignore_case)
65    }
66}
67
68pub trait StrFind {
69    fn start_with(&self, s: &[u8]) -> bool;
70    fn index_of(&self, s: &[u8]) -> Option<usize>;
71}
72
73impl StrFind for [u8] {
74    fn start_with(&self, s: &[u8]) -> bool {
75        if self.len() >= s.len() {
76            let mut i = 0;
77            while i < s.len() {
78                if s[i] != self[i] {
79                    return false;
80                }
81                i = i + 1;
82            }
83            return true;
84        }
85
86        false
87    }
88
89    fn index_of(&self, s: &[u8]) -> Option<usize> {
90        let mut i = 0;
91
92        while i + s.len() <= self.len() {
93            let lhs = &self[i..i + s.len()];
94
95            if lhs == s {
96                return Some(i);
97            }
98
99            i = i + 1;
100        }
101
102        None
103    }
104}
105
106impl StrFind for Vec<u8> {
107    fn start_with(&self, s: &[u8]) -> bool {
108        <[u8]>::start_with(self, s)
109    }
110
111    fn index_of(&self, s: &[u8]) -> Option<usize> {
112        <[u8]>::index_of(self, s)
113    }
114}
115
116pub trait ToInt {
117    fn to_int<R>(&self) -> Result<R, String>
118    where
119        R: FromStr;
120}
121
122impl ToInt for [u8] {
123    fn to_int<R>(&self) -> Result<R, String>
124    where
125        R: FromStr,
126    {
127        match std::str::from_utf8(self) {
128            Ok(s) => match R::from_str(s) {
129                Ok(i) => return Ok(i),
130                Err(_) => {
131                    return Err(String::from("std::num::ParseIntError"));
132                }
133            },
134            Err(e) => {
135                // std::str::Utf8Error
136                let s: String = format!("{}", e);
137                return Err(s);
138            }
139        }
140    }
141}
142
143impl ToInt for Vec<u8> {
144    fn to_int<R>(&self) -> Result<R, String>
145    where
146        R: FromStr,
147    {
148        <[u8]>::to_int(self)
149    }
150}
151
152pub trait FromRawStr: Sized {
153    type Err;
154    fn from_raw_str(s: &[u8]) -> Result<Self, Self::Err>;
155}