(&self, s: &str)
| 112 | } |
| 113 | |
| 114 | fn decode(&self, s: &str) -> Result<Vec<u8>, EvalError> { |
| 115 | // Process input in chunks of four bytes, after filtering out any bytes |
| 116 | // that represent whitespace. Each byte is decoded into a sextet |
| 117 | // according to the reverse charset mapping maintained in |
| 118 | // `Self::decode_sextet`. The four sextets are converted to three octets |
| 119 | // and emitted. |
| 120 | // |
| 121 | // When the last character in a chunk is `=` or the last two characters |
| 122 | // in a chunk are both `=`, the chunk is missing its last one or two |
| 123 | // sextets, respectively. Octets that are entirely determined by missing |
| 124 | // sextets are elided. Octets that are partially determined by a missing |
| 125 | // sextet assume the sextet was zero. |
| 126 | // |
| 127 | // It is an error for a `=` character to appear in another position in |
| 128 | // a chunk. It is also an error if a chunk is incomplete. |
| 129 | |
| 130 | let mut buf = vec![]; |
| 131 | let mut bytes = s |
| 132 | .as_bytes() |
| 133 | .iter() |
| 134 | .copied() |
| 135 | .filter(|ch| !matches!(ch, b' ' | b'\t' | b'\n' | b'\r')); |
| 136 | loop { |
| 137 | match (bytes.next(), bytes.next(), bytes.next(), bytes.next()) { |
| 138 | (Some(c1), Some(c2), Some(b'='), Some(b'=')) => { |
| 139 | let s1 = Self::decode_sextet(c1)?; |
| 140 | let s2 = Self::decode_sextet(c2)?; |
| 141 | buf.push((s1 << 2) | ((s2 & 0b110000) >> 4)); |
| 142 | } |
| 143 | (Some(c1), Some(c2), Some(c3), Some(b'=')) => { |
| 144 | let s1 = Self::decode_sextet(c1)?; |
| 145 | let s2 = Self::decode_sextet(c2)?; |
| 146 | let s3 = Self::decode_sextet(c3)?; |
| 147 | buf.push((s1 << 2) | ((s2 & 0b110000) >> 4)); |
| 148 | buf.push(((s2 & 0b001111) << 4) | ((s3 & 0b111100) >> 2)); |
| 149 | } |
| 150 | (Some(b'='), _, _, _) | (_, Some(b'='), _, _) | (_, _, Some(b'='), _) => { |
| 151 | return Err(EvalError::InvalidBase64Equals); |
| 152 | } |
| 153 | (Some(c1), Some(c2), Some(c3), Some(c4)) => { |
| 154 | let s1 = Self::decode_sextet(c1)?; |
| 155 | let s2 = Self::decode_sextet(c2)?; |
| 156 | let s3 = Self::decode_sextet(c3)?; |
| 157 | let s4 = Self::decode_sextet(c4)?; |
| 158 | buf.push((s1 << 2) | ((s2 & 0b110000) >> 4)); |
| 159 | buf.push(((s2 & 0b001111) << 4) | ((s3 & 0b111100) >> 2)); |
| 160 | buf.push(((s3 & 0b000011) << 6) | s4); |
| 161 | } |
| 162 | (None, None, None, None) => return Ok(buf), |
| 163 | _ => return Err(EvalError::InvalidBase64EndSequence), |
| 164 | } |
| 165 | } |
| 166 | } |
| 167 | } |
| 168 | |
| 169 | struct EscapeFormat; |
no test coverage detected