]> git.proxmox.com Git - cargo.git/blobdiff - vendor/bstr/src/impls.rs
New upstream version 0.52.0
[cargo.git] / vendor / bstr / src / impls.rs
index 375e5be7d9525b69117ca68319412fc57f673c71..85a27ba7786729aa96d8bde37d5e34545dce1817 100644 (file)
@@ -33,7 +33,7 @@ macro_rules! impl_partial_eq_cow {
             #[inline]
             fn eq(&self, other: &$lhs) -> bool {
                 let this: &[u8] = (&**other).as_ref();
-                PartialEq::eq(this, other.as_bytes())
+                PartialEq::eq(this, self.as_bytes())
             }
         }
     };
@@ -67,20 +67,20 @@ mod bstring {
     use std::iter::FromIterator;
     use std::ops;
 
-    use bstr::BStr;
-    use bstring::BString;
-    use ext_vec::ByteVec;
+    use crate::bstr::BStr;
+    use crate::bstring::BString;
+    use crate::ext_vec::ByteVec;
 
     impl fmt::Display for BString {
         #[inline]
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             fmt::Display::fmt(self.as_bstr(), f)
         }
     }
 
     impl fmt::Debug for BString {
         #[inline]
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             fmt::Debug::fmt(self.as_bstr(), f)
         }
     }
@@ -308,33 +308,99 @@ mod bstr {
     use core::fmt;
     use core::ops;
 
-    use bstr::BStr;
-    use ext_slice::ByteSlice;
+    use crate::bstr::BStr;
+    use crate::ext_slice::ByteSlice;
 
     impl fmt::Display for BStr {
         #[inline]
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-            for chunk in self.utf8_chunks() {
-                f.write_str(chunk.valid())?;
-                if !chunk.invalid().is_empty() {
-                    f.write_str("\u{FFFD}")?;
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            /// Write the given bstr (lossily) to the given formatter.
+            fn write_bstr(
+                f: &mut fmt::Formatter<'_>,
+                bstr: &BStr,
+            ) -> Result<(), fmt::Error> {
+                for chunk in bstr.utf8_chunks() {
+                    f.write_str(chunk.valid())?;
+                    if !chunk.invalid().is_empty() {
+                        f.write_str("\u{FFFD}")?;
+                    }
                 }
+                Ok(())
+            }
+
+            /// Write 'num' fill characters to the given formatter.
+            fn write_pads(
+                f: &mut fmt::Formatter<'_>,
+                num: usize,
+            ) -> fmt::Result {
+                let fill = f.fill();
+                for _ in 0..num {
+                    f.write_fmt(format_args!("{}", fill))?;
+                }
+                Ok(())
+            }
+
+            if let Some(align) = f.align() {
+                let width = f.width().unwrap_or(0);
+                let nchars = self.chars().count();
+                let remaining_pads = width.saturating_sub(nchars);
+                match align {
+                    fmt::Alignment::Left => {
+                        write_bstr(f, self)?;
+                        write_pads(f, remaining_pads)?;
+                    }
+                    fmt::Alignment::Right => {
+                        write_pads(f, remaining_pads)?;
+                        write_bstr(f, self)?;
+                    }
+                    fmt::Alignment::Center => {
+                        let half = remaining_pads / 2;
+                        let second_half = if remaining_pads % 2 == 0 {
+                            half
+                        } else {
+                            half + 1
+                        };
+                        write_pads(f, half)?;
+                        write_bstr(f, self)?;
+                        write_pads(f, second_half)?;
+                    }
+                }
+                Ok(())
+            } else {
+                write_bstr(f, self)?;
+                Ok(())
             }
-            Ok(())
         }
     }
 
     impl fmt::Debug for BStr {
         #[inline]
-        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             write!(f, "\"")?;
             for (s, e, ch) in self.char_indices() {
-                if ch == '\u{FFFD}' {
-                    for &b in self[s..e].as_bytes() {
-                        write!(f, r"\x{:X}", b)?;
+                match ch {
+                    '\0' => write!(f, "\\0")?,
+                    '\u{FFFD}' => {
+                        let bytes = self[s..e].as_bytes();
+                        if bytes == b"\xEF\xBF\xBD" {
+                            write!(f, "{}", ch.escape_debug())?;
+                        } else {
+                            for &b in self[s..e].as_bytes() {
+                                write!(f, r"\x{:02X}", b)?;
+                            }
+                        }
+                    }
+                    // ASCII control characters except \0, \n, \r, \t
+                    '\x01'..='\x08'
+                    | '\x0b'
+                    | '\x0c'
+                    | '\x0e'..='\x19'
+                    | '\x7f' => {
+                        write!(f, "\\x{:02x}", ch as u32)?;
+                    }
+                    '\n' | '\r' | '\t' | _ => {
+                        write!(f, "{}", ch.escape_debug())?;
                     }
-                } else {
-                    write!(f, "{}", ch.escape_debug())?;
                 }
             }
             write!(f, "\"")?;
@@ -539,6 +605,22 @@ mod bstr {
         }
     }
 
+    #[cfg(feature = "std")]
+    impl From<Box<[u8]>> for Box<BStr> {
+        #[inline]
+        fn from(s: Box<[u8]>) -> Box<BStr> {
+            BStr::from_boxed_bytes(s)
+        }
+    }
+
+    #[cfg(feature = "std")]
+    impl From<Box<BStr>> for Box<[u8]> {
+        #[inline]
+        fn from(s: Box<BStr>) -> Box<[u8]> {
+            BStr::into_boxed_bytes(s)
+        }
+    }
+
     impl Eq for BStr {}
 
     impl PartialEq<BStr> for BStr {
@@ -606,7 +688,7 @@ mod bstr_serde {
         Serializer,
     };
 
-    use bstr::BStr;
+    use crate::bstr::BStr;
 
     impl Serialize for BStr {
         #[inline]
@@ -665,7 +747,7 @@ mod bstring_serde {
         Serialize, Serializer,
     };
 
-    use bstring::BString;
+    use crate::bstring::BString;
 
     impl Serialize for BString {
         #[inline]
@@ -743,14 +825,123 @@ mod bstring_serde {
     }
 }
 
+#[cfg(test)]
+mod display {
+    use crate::bstring::BString;
+    use crate::ByteSlice;
+
+    #[test]
+    fn clean() {
+        assert_eq!(&format!("{}", &b"abc".as_bstr()), "abc");
+        assert_eq!(&format!("{}", &b"\xf0\x28\x8c\xbc".as_bstr()), "�(��");
+    }
+
+    #[test]
+    fn width_bigger_than_bstr() {
+        assert_eq!(&format!("{:<7}!", &b"abc".as_bstr()), "abc    !");
+        assert_eq!(&format!("{:>7}!", &b"abc".as_bstr()), "    abc!");
+        assert_eq!(&format!("{:^7}!", &b"abc".as_bstr()), "  abc  !");
+        assert_eq!(&format!("{:^6}!", &b"abc".as_bstr()), " abc  !");
+        assert_eq!(&format!("{:-<7}!", &b"abc".as_bstr()), "abc----!");
+        assert_eq!(&format!("{:->7}!", &b"abc".as_bstr()), "----abc!");
+        assert_eq!(&format!("{:-^7}!", &b"abc".as_bstr()), "--abc--!");
+        assert_eq!(&format!("{:-^6}!", &b"abc".as_bstr()), "-abc--!");
+
+        assert_eq!(
+            &format!("{:<7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            "�(��   !"
+        );
+        assert_eq!(
+            &format!("{:>7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            "   �(��!"
+        );
+        assert_eq!(
+            &format!("{:^7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            " �(��  !"
+        );
+        assert_eq!(
+            &format!("{:^6}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            " �(�� !"
+        );
+
+        assert_eq!(
+            &format!("{:-<7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            "�(��---!"
+        );
+        assert_eq!(
+            &format!("{:->7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            "---�(��!"
+        );
+        assert_eq!(
+            &format!("{:-^7}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            "-�(��--!"
+        );
+        assert_eq!(
+            &format!("{:-^6}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            "-�(��-!"
+        );
+    }
+
+    #[test]
+    fn width_lesser_than_bstr() {
+        assert_eq!(&format!("{:<2}!", &b"abc".as_bstr()), "abc!");
+        assert_eq!(&format!("{:>2}!", &b"abc".as_bstr()), "abc!");
+        assert_eq!(&format!("{:^2}!", &b"abc".as_bstr()), "abc!");
+        assert_eq!(&format!("{:-<2}!", &b"abc".as_bstr()), "abc!");
+        assert_eq!(&format!("{:->2}!", &b"abc".as_bstr()), "abc!");
+        assert_eq!(&format!("{:-^2}!", &b"abc".as_bstr()), "abc!");
+
+        assert_eq!(
+            &format!("{:<3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            "�(��!"
+        );
+        assert_eq!(
+            &format!("{:>3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            "�(��!"
+        );
+        assert_eq!(
+            &format!("{:^3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            "�(��!"
+        );
+        assert_eq!(
+            &format!("{:^2}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            "�(��!"
+        );
+
+        assert_eq!(
+            &format!("{:-<3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            "�(��!"
+        );
+        assert_eq!(
+            &format!("{:->3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            "�(��!"
+        );
+        assert_eq!(
+            &format!("{:-^3}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            "�(��!"
+        );
+        assert_eq!(
+            &format!("{:-^2}!", &b"\xf0\x28\x8c\xbc".as_bstr()),
+            "�(��!"
+        );
+    }
+
+    quickcheck::quickcheck! {
+        fn total_length(bstr: BString) -> bool {
+            let size = bstr.chars().count();
+            format!("{:<1$}", bstr.as_bstr(), size).chars().count() >= size
+        }
+    }
+}
+
 #[cfg(test)]
 mod bstring_arbitrary {
-    use bstring::BString;
+    use crate::bstring::BString;
 
     use quickcheck::{Arbitrary, Gen};
 
     impl Arbitrary for BString {
-        fn arbitrary<G: Gen>(g: &mut G) -> BString {
+        fn arbitrary(g: &mut Gen) -> BString {
             BString::from(Vec::<u8>::arbitrary(g))
         }
 
@@ -759,3 +950,38 @@ mod bstring_arbitrary {
         }
     }
 }
+
+#[test]
+fn test_debug() {
+    use crate::{ByteSlice, B};
+
+    assert_eq!(
+        r#""\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp""#,
+        format!("{:?}", b"\0\0\0 ftypisom\0\0\x02\0isomiso2avc1mp".as_bstr()),
+    );
+
+    // Tests that if the underlying bytes contain the UTF-8 encoding of the
+    // replacement codepoint, then we emit the codepoint just like other
+    // non-printable Unicode characters.
+    assert_eq!(
+        b"\"\\xFF\xEF\xBF\xBD\\xFF\"".as_bstr(),
+        // Before fixing #72, the output here would be:
+        //   \\xFF\\xEF\\xBF\\xBD\\xFF
+        B(&format!("{:?}", b"\xFF\xEF\xBF\xBD\xFF".as_bstr())).as_bstr(),
+    );
+}
+
+// See: https://github.com/BurntSushi/bstr/issues/82
+#[test]
+fn test_cows_regression() {
+    use crate::ByteSlice;
+    use std::borrow::Cow;
+
+    let c1 = Cow::from(b"hello bstr".as_bstr());
+    let c2 = b"goodbye bstr".as_bstr();
+    assert_ne!(c1, c2);
+
+    let c3 = Cow::from("hello str");
+    let c4 = "goodbye str";
+    assert_ne!(c3, c4);
+}