Try to decode the entire buffer with strict flags (fast path). Returns Ok(Some(wide_chars)) on success, Ok(None) on decode error, or Err on OS error.
(
code_page: u32,
data: &[u8],
vm: &VirtualMachine,
)
| 1092 | /// Returns Ok(Some(wide_chars)) on success, Ok(None) on decode error, |
| 1093 | /// or Err on OS error. |
| 1094 | fn try_decode_code_page_strict( |
| 1095 | code_page: u32, |
| 1096 | data: &[u8], |
| 1097 | vm: &VirtualMachine, |
| 1098 | ) -> PyResult<Option<Vec<u16>>> { |
| 1099 | use windows_sys::Win32::Globalization::{MB_ERR_INVALID_CHARS, MultiByteToWideChar}; |
| 1100 | |
| 1101 | let mut flags = MB_ERR_INVALID_CHARS; |
| 1102 | |
| 1103 | loop { |
| 1104 | let size = unsafe { |
| 1105 | MultiByteToWideChar( |
| 1106 | code_page, |
| 1107 | flags, |
| 1108 | data.as_ptr().cast(), |
| 1109 | data.len() as i32, |
| 1110 | core::ptr::null_mut(), |
| 1111 | 0, |
| 1112 | ) |
| 1113 | }; |
| 1114 | if size > 0 { |
| 1115 | let mut buffer = vec![0u16; size as usize]; |
| 1116 | let result = unsafe { |
| 1117 | MultiByteToWideChar( |
| 1118 | code_page, |
| 1119 | flags, |
| 1120 | data.as_ptr().cast(), |
| 1121 | data.len() as i32, |
| 1122 | buffer.as_mut_ptr(), |
| 1123 | size, |
| 1124 | ) |
| 1125 | }; |
| 1126 | if result > 0 { |
| 1127 | buffer.truncate(result as usize); |
| 1128 | return Ok(Some(buffer)); |
| 1129 | } |
| 1130 | } |
| 1131 | |
| 1132 | let err_code = std::io::Error::last_os_error().raw_os_error().unwrap_or(0); |
| 1133 | // ERROR_INVALID_FLAGS = 1004 |
| 1134 | if flags != 0 && err_code == 1004 { |
| 1135 | flags = 0; |
| 1136 | continue; |
| 1137 | } |
| 1138 | // ERROR_NO_UNICODE_TRANSLATION = 1113 |
| 1139 | if err_code == 1113 { |
| 1140 | return Ok(None); |
| 1141 | } |
| 1142 | let err = std::io::Error::last_os_error(); |
| 1143 | return Err(vm.new_os_error(format!("code_page_decode: {err}"))); |
| 1144 | } |
| 1145 | } |
| 1146 | |
| 1147 | /// Decode byte by byte with error handling (slow path). |
| 1148 | fn decode_code_page_errors( |
no test coverage detected