Search code examples
rustrust-tokio

How to trim a BytesMut from bytes crate?


Suppose I have a BytesMut, I want to be able to make it trim_bytes.

let some_bytes = BytesMut::from("  hello world  ");
let trim_bytes = some_bytes.some_trim_method();
// trim_bytes = BytesMut::From("hello world");   

some_trim_method() is what I've been looking for but there isn't such method in crate.


Solution

  • You can also create your own version of trim function for bytes

    const TAB: &u8 = &b'\t';
    const SPACE: &u8 = &b' ';
    
    fn is_whitespace(c: &u8) -> bool {
        c == TAB || c == SPACE
    }
    
    fn is_not_whitespace(c: &u8) -> bool {
        !is_whitespace(c)
    }
    
    fn trim_bytes(s: &[u8]) -> &[u8] {
      let l = s.len();
      let (mut i, mut j, mut k) = (0, l - 1, 0);
      loop {
          if (is_not_whitespace(&s[i]) && is_not_whitespace(&s[j])) || i > j || k >= l {
              break;
          }
    
          if is_whitespace(&s[i]) {
              i += 1;
          }
    
          if is_whitespace(&s[j]) {
              j -= 1;
          }
    
          k += 1
      }
      return &s[i..=j];
    }
    
    fn main() {
        let result = trim_bytes(&some_bytes);
        println!("{:?}", result);
        assert_eq!(b"hello world", result);
    }
    

    or implement trim method on byte type

    trait TrimBytes {
        fn trim(&self) -> &Self;
    }
    
    impl TrimBytes for [u8] {
        fn trim(&self) -> &[u8] {
            if let Some(first) = self.iter().position(is_not_whitespace) {
                if let Some(last) = self.iter().rposition(is_not_whitespace) {
                    &self[first..last + 1]
                } else {
                    unreachable!();
                }
            } else {
                &[]
            }
        }
    }
    
    fn main() {
        let result = some_bytes.trim();
        println!("{:?}", result);
        assert_eq!(b"hello world", result);
    }