@@ -71,7 +71,7 @@ impl std::error::Error for EscapeError {}
71
71
/// | `&` | `&`
72
72
/// | `'` | `'`
73
73
/// | `"` | `"`
74
- pub fn escape ( raw : & str ) -> Cow < [ u8 ] > {
74
+ pub fn escape ( raw : & str ) -> Cow < str > {
75
75
_escape ( raw, |ch| matches ! ( ch, b'<' | b'>' | b'&' | b'\'' | b'\"' ) )
76
76
}
77
77
@@ -88,25 +88,25 @@ pub fn escape(raw: &str) -> Cow<[u8]> {
88
88
/// | `<` | `<`
89
89
/// | `>` | `>`
90
90
/// | `&` | `&`
91
- pub fn partial_escape ( raw : & str ) -> Cow < [ u8 ] > {
91
+ pub fn partial_escape ( raw : & str ) -> Cow < str > {
92
92
_escape ( raw, |ch| matches ! ( ch, b'<' | b'>' | b'&' ) )
93
93
}
94
94
95
95
/// Escapes an `&str` and replaces a subset of xml special characters (`<`, `>`,
96
96
/// `&`, `'`, `"`) with their corresponding xml escaped value.
97
- fn _escape < F : Fn ( u8 ) -> bool > ( raw : & str , escape_chars : F ) -> Cow < [ u8 ] > {
98
- let raw = raw. as_bytes ( ) ;
97
+ fn _escape < F : Fn ( u8 ) -> bool > ( raw : & str , escape_chars : F ) -> Cow < str > {
98
+ let bytes = raw. as_bytes ( ) ;
99
99
let mut escaped = None ;
100
- let mut bytes = raw . iter ( ) ;
100
+ let mut iter = bytes . iter ( ) ;
101
101
let mut pos = 0 ;
102
- while let Some ( i) = bytes . position ( |& b| escape_chars ( b) ) {
102
+ while let Some ( i) = iter . position ( |& b| escape_chars ( b) ) {
103
103
if escaped. is_none ( ) {
104
104
escaped = Some ( Vec :: with_capacity ( raw. len ( ) ) ) ;
105
105
}
106
106
let escaped = escaped. as_mut ( ) . expect ( "initialized" ) ;
107
107
let new_pos = pos + i;
108
- escaped. extend_from_slice ( & raw [ pos..new_pos] ) ;
109
- match raw [ new_pos] {
108
+ escaped. extend_from_slice ( & bytes [ pos..new_pos] ) ;
109
+ match bytes [ new_pos] {
110
110
b'<' => escaped. extend_from_slice ( b"<" ) ,
111
111
b'>' => escaped. extend_from_slice ( b">" ) ,
112
112
b'\'' => escaped. extend_from_slice ( b"'" ) ,
@@ -118,10 +118,14 @@ fn _escape<F: Fn(u8) -> bool>(raw: &str, escape_chars: F) -> Cow<[u8]> {
118
118
}
119
119
120
120
if let Some ( mut escaped) = escaped {
121
- if let Some ( raw) = raw . get ( pos..) {
121
+ if let Some ( raw) = bytes . get ( pos..) {
122
122
escaped. extend_from_slice ( raw) ;
123
123
}
124
- Cow :: Owned ( escaped)
124
+ // SAFETY: we operate on UTF-8 input and search for an one byte chars only,
125
+ // so all slices that was put to the `escaped` is a valid UTF-8 encoded strings
126
+ // TODO: Can be replaced with `unsafe { String::from_utf8_unchecked() }`
127
+ // if unsafe code will be allowed
128
+ Cow :: Owned ( String :: from_utf8 ( escaped) . unwrap ( ) )
125
129
} else {
126
130
Cow :: Borrowed ( raw)
127
131
}
@@ -1745,24 +1749,24 @@ fn test_unescape_with() {
1745
1749
1746
1750
#[ test]
1747
1751
fn test_escape ( ) {
1748
- assert_eq ! ( & * escape( "test" ) , b "test") ;
1749
- assert_eq ! ( & * escape( "<test>" ) , b "<test>") ;
1750
- assert_eq ! ( & * escape( "\" a\" bc" ) , b ""a"bc") ;
1751
- assert_eq ! ( & * escape( "\" a\" b&c" ) , b ""a"b&c") ;
1752
+ assert_eq ! ( & * escape( "test" ) , "test" ) ;
1753
+ assert_eq ! ( & * escape( "<test>" ) , "<test>" ) ;
1754
+ assert_eq ! ( & * escape( "\" a\" bc" ) , ""a"bc" ) ;
1755
+ assert_eq ! ( & * escape( "\" a\" b&c" ) , ""a"b&c" ) ;
1752
1756
assert_eq ! (
1753
1757
& * escape( "prefix_\" a\" b&<>c" ) ,
1754
- "prefix_"a"b&<>c" . as_bytes ( )
1758
+ "prefix_"a"b&<>c"
1755
1759
) ;
1756
1760
}
1757
1761
1758
1762
#[ test]
1759
1763
fn test_partial_escape ( ) {
1760
- assert_eq ! ( & * partial_escape( "test" ) , b "test") ;
1761
- assert_eq ! ( & * partial_escape( "<test>" ) , b "<test>") ;
1762
- assert_eq ! ( & * partial_escape( "\" a\" bc" ) , b "\" a\" bc") ;
1763
- assert_eq ! ( & * partial_escape( "\" a\" b&c" ) , b "\" a\" b&c") ;
1764
+ assert_eq ! ( & * partial_escape( "test" ) , "test" ) ;
1765
+ assert_eq ! ( & * partial_escape( "<test>" ) , "<test>" ) ;
1766
+ assert_eq ! ( & * partial_escape( "\" a\" bc" ) , "\" a\" bc" ) ;
1767
+ assert_eq ! ( & * partial_escape( "\" a\" b&c" ) , "\" a\" b&c" ) ;
1764
1768
assert_eq ! (
1765
1769
& * partial_escape( "prefix_\" a\" b&<>c" ) ,
1766
- "prefix_\" a\" b&<>c" . as_bytes ( )
1770
+ "prefix_\" a\" b&<>c"
1767
1771
) ;
1768
1772
}
0 commit comments