Decode byte by byte with error handling (slow path).
(
code_page: u32,
data: &[u8],
errors: &str,
is_final: bool,
encoding_name: &str,
vm: &VirtualMachine,
)
| 1146 | |
| 1147 | /// Decode byte by byte with error handling (slow path). |
| 1148 | fn decode_code_page_errors( |
| 1149 | code_page: u32, |
| 1150 | data: &[u8], |
| 1151 | errors: &str, |
| 1152 | is_final: bool, |
| 1153 | encoding_name: &str, |
| 1154 | vm: &VirtualMachine, |
| 1155 | ) -> PyResult<(PyStrRef, usize)> { |
| 1156 | use crate::builtins::PyTuple; |
| 1157 | use crate::common::wtf8::Wtf8Buf; |
| 1158 | use windows_sys::Win32::Globalization::{MB_ERR_INVALID_CHARS, MultiByteToWideChar}; |
| 1159 | |
| 1160 | let len = data.len(); |
| 1161 | let encoding_str = vm.ctx.new_str(encoding_name); |
| 1162 | let reason_str = vm |
| 1163 | .ctx |
| 1164 | .new_str("No mapping for the Unicode character exists in the target code page."); |
| 1165 | |
| 1166 | // For strict+final, find the failing position and raise |
| 1167 | if errors == "strict" && is_final { |
| 1168 | // Find the exact failing byte position by trying byte by byte |
| 1169 | let mut fail_pos = 0; |
| 1170 | let mut flags_s: u32 = MB_ERR_INVALID_CHARS; |
| 1171 | let mut buf = [0u16; 2]; |
| 1172 | while fail_pos < len { |
| 1173 | let mut in_size = 1; |
| 1174 | let mut found = false; |
| 1175 | while in_size <= 4 && fail_pos + in_size <= len { |
| 1176 | let outsize = unsafe { |
| 1177 | MultiByteToWideChar( |
| 1178 | code_page, |
| 1179 | flags_s, |
| 1180 | data[fail_pos..].as_ptr().cast(), |
| 1181 | in_size as i32, |
| 1182 | buf.as_mut_ptr(), |
| 1183 | 2, |
| 1184 | ) |
| 1185 | }; |
| 1186 | if outsize > 0 { |
| 1187 | fail_pos += in_size; |
| 1188 | found = true; |
| 1189 | break; |
| 1190 | } |
| 1191 | let err_code = std::io::Error::last_os_error().raw_os_error().unwrap_or(0); |
| 1192 | if err_code == 1004 && flags_s != 0 { |
| 1193 | flags_s = 0; |
| 1194 | continue; |
| 1195 | } |
| 1196 | in_size += 1; |
| 1197 | } |
| 1198 | if !found { |
| 1199 | break; |
| 1200 | } |
| 1201 | } |
| 1202 | let object = vm.ctx.new_bytes(data.to_vec()); |
| 1203 | return Err(vm.new_unicode_decode_error_real( |
| 1204 | encoding_str, |
| 1205 | object, |
no test coverage detected