1
1
use crate :: {
2
2
engine:: { general_purpose:: INVALID_VALUE , DecodeMetadata , DecodePaddingMode } ,
3
- DecodeError , PAD_BYTE ,
3
+ DecodeError , DecodeSliceError , PAD_BYTE ,
4
4
} ;
5
5
6
6
/// Decode the last 0-4 bytes, checking for trailing set bits and padding per the provided
@@ -16,11 +16,11 @@ pub(crate) fn decode_suffix(
16
16
decode_table : & [ u8 ; 256 ] ,
17
17
decode_allow_trailing_bits : bool ,
18
18
padding_mode : DecodePaddingMode ,
19
- ) -> Result < DecodeMetadata , DecodeError > {
19
+ ) -> Result < DecodeMetadata , DecodeSliceError > {
20
20
debug_assert ! ( ( input. len( ) - input_index) <= 4 ) ;
21
21
22
- // Decode any leftovers that might not be a complete input chunk of 8 bytes.
23
- // Use a u64 as a stack-resident 8 byte buffer.
22
+ // Decode any leftovers that might not be a complete input chunk of 4 bytes.
23
+ // Use a u32 as a stack-resident 4 byte buffer.
24
24
let mut morsels_in_leftover = 0 ;
25
25
let mut padding_bytes_count = 0 ;
26
26
// offset from input_index
@@ -44,22 +44,14 @@ pub(crate) fn decode_suffix(
44
44
// may be treated as an error condition.
45
45
46
46
if leftover_index < 2 {
47
- // Check for case #2.
48
- let bad_padding_index = input_index
49
- + if padding_bytes_count > 0 {
50
- // If we've already seen padding, report the first padding index.
51
- // This is to be consistent with the normal decode logic: it will report an
52
- // error on the first padding character (since it doesn't expect to see
53
- // anything but actual encoded data).
54
- // This could only happen if the padding started in the previous quad since
55
- // otherwise this case would have been hit at i == 4 if it was the same
56
- // quad.
57
- first_padding_offset
58
- } else {
59
- // haven't seen padding before, just use where we are now
60
- leftover_index
61
- } ;
62
- return Err ( DecodeError :: InvalidByte ( bad_padding_index, b) ) ;
47
+ // Check for error #2.
48
+ // Either the previous byte was padding, in which case we would have already hit
49
+ // this case, or it wasn't, in which case this is the first such error.
50
+ debug_assert ! (
51
+ leftover_index == 0 || ( leftover_index == 1 && padding_bytes_count == 0 )
52
+ ) ;
53
+ let bad_padding_index = input_index + leftover_index;
54
+ return Err ( DecodeError :: InvalidByte ( bad_padding_index, b) . into ( ) ) ;
63
55
}
64
56
65
57
if padding_bytes_count == 0 {
@@ -75,10 +67,9 @@ pub(crate) fn decode_suffix(
75
67
// non-suffix '=' in trailing chunk either. Report error as first
76
68
// erroneous padding.
77
69
if padding_bytes_count > 0 {
78
- return Err ( DecodeError :: InvalidByte (
79
- input_index + first_padding_offset,
80
- PAD_BYTE ,
81
- ) ) ;
70
+ return Err (
71
+ DecodeError :: InvalidByte ( input_index + first_padding_offset, PAD_BYTE ) . into ( ) ,
72
+ ) ;
82
73
}
83
74
84
75
last_symbol = b;
@@ -87,7 +78,7 @@ pub(crate) fn decode_suffix(
87
78
// Pack the leftovers from left to right.
88
79
let morsel = decode_table[ b as usize ] ;
89
80
if morsel == INVALID_VALUE {
90
- return Err ( DecodeError :: InvalidByte ( input_index + leftover_index, b) ) ;
81
+ return Err ( DecodeError :: InvalidByte ( input_index + leftover_index, b) . into ( ) ) ;
91
82
}
92
83
93
84
morsels[ morsels_in_leftover] = morsel;
@@ -97,24 +88,22 @@ pub(crate) fn decode_suffix(
97
88
// If there was 1 trailing byte, and it was valid, and we got to this point without hitting
98
89
// an invalid byte, now we can report invalid length
99
90
if !input. is_empty ( ) && morsels_in_leftover < 2 {
100
- return Err ( DecodeError :: InvalidLength (
101
- input_index + morsels_in_leftover,
102
- ) ) ;
91
+ return Err ( DecodeError :: InvalidLength ( input_index + morsels_in_leftover) . into ( ) ) ;
103
92
}
104
93
105
94
match padding_mode {
106
95
DecodePaddingMode :: Indifferent => { /* everything we care about was already checked */ }
107
96
DecodePaddingMode :: RequireCanonical => {
108
97
// allow empty input
109
98
if ( padding_bytes_count + morsels_in_leftover) % 4 != 0 {
110
- return Err ( DecodeError :: InvalidPadding ) ;
99
+ return Err ( DecodeError :: InvalidPadding . into ( ) ) ;
111
100
}
112
101
}
113
102
DecodePaddingMode :: RequireNone => {
114
103
if padding_bytes_count > 0 {
115
104
// check at the end to make sure we let the cases of padding that should be InvalidByte
116
105
// get hit
117
- return Err ( DecodeError :: InvalidPadding ) ;
106
+ return Err ( DecodeError :: InvalidPadding . into ( ) ) ;
118
107
}
119
108
}
120
109
}
@@ -127,7 +116,7 @@ pub(crate) fn decode_suffix(
127
116
// bits in the bottom 6, but would be a non-canonical encoding. So, we calculate a
128
117
// mask based on how many bits are used for just the canonical encoding, and optionally
129
118
// error if any other bits are set. In the example of one encoded byte -> 2 symbols,
130
- // 2 symbols can technically encode 12 bits, but the last 4 are non canonical, and
119
+ // 2 symbols can technically encode 12 bits, but the last 4 are non- canonical, and
131
120
// useless since there are no more symbols to provide the necessary 4 additional bits
132
121
// to finish the second original byte.
133
122
@@ -147,16 +136,18 @@ pub(crate) fn decode_suffix(
147
136
return Err ( DecodeError :: InvalidLastSymbol (
148
137
input_index + morsels_in_leftover - 1 ,
149
138
last_symbol,
150
- ) ) ;
139
+ )
140
+ . into ( ) ) ;
151
141
}
152
142
153
143
// Strangely, this approach benchmarks better than writing bytes one at a time,
154
144
// or copy_from_slice into output.
155
145
for _ in 0 ..leftover_bytes_to_append {
156
146
let hi_byte = ( leftover_num >> 24 ) as u8 ;
157
147
leftover_num <<= 8 ;
158
- // TODO use checked writes
159
- output[ output_index] = hi_byte;
148
+ * output
149
+ . get_mut ( output_index)
150
+ . ok_or ( DecodeSliceError :: OutputSliceTooSmall ) ? = hi_byte;
160
151
output_index += 1 ;
161
152
}
162
153
0 commit comments