(instance: PyObjectRef, vm: &VirtualMachine)
| 1142 | |
| 1143 | #[pygetset] |
| 1144 | pub fn value(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyObjectRef> { |
| 1145 | let zelf: &Py<Self> = instance |
| 1146 | .downcast_ref() |
| 1147 | .ok_or_else(|| vm.new_type_error("cannot get value of instance"))?; |
| 1148 | |
| 1149 | // Get _type_ from class |
| 1150 | let cls = zelf.class(); |
| 1151 | let type_attr = cls |
| 1152 | .as_object() |
| 1153 | .get_attr("_type_", vm) |
| 1154 | .map_err(|_| vm.new_type_error("no _type_ attribute"))?; |
| 1155 | let type_code = type_attr.str(vm)?.to_string(); |
| 1156 | |
| 1157 | // Special handling for c_char_p (z) and c_wchar_p (Z) |
| 1158 | // z_get, Z_get - dereference pointer to get string |
| 1159 | if type_code == "z" { |
| 1160 | // c_char_p: read pointer from buffer, dereference to get bytes string |
| 1161 | let buffer = zelf.0.buffer.read(); |
| 1162 | let ptr = super::base::read_ptr_from_buffer(&buffer); |
| 1163 | if ptr == 0 { |
| 1164 | return Ok(vm.ctx.none()); |
| 1165 | } |
| 1166 | // Read null-terminated string at the address |
| 1167 | unsafe { |
| 1168 | let cstr = core::ffi::CStr::from_ptr(ptr as _); |
| 1169 | return Ok(vm.ctx.new_bytes(cstr.to_bytes().to_vec()).into()); |
| 1170 | } |
| 1171 | } |
| 1172 | if type_code == "Z" { |
| 1173 | // c_wchar_p: read pointer from buffer, dereference to get wide string |
| 1174 | let buffer = zelf.0.buffer.read(); |
| 1175 | let ptr = super::base::read_ptr_from_buffer(&buffer); |
| 1176 | if ptr == 0 { |
| 1177 | return Ok(vm.ctx.none()); |
| 1178 | } |
| 1179 | // Read null-terminated wide string at the address |
| 1180 | // Windows: wchar_t = u16 (UTF-16) -> use Wtf8Buf::from_wide for surrogate pairs |
| 1181 | // Unix: wchar_t = i32 (UTF-32) -> convert via char::from_u32 |
| 1182 | unsafe { |
| 1183 | let w_ptr = ptr as *const libc::wchar_t; |
| 1184 | let len = libc::wcslen(w_ptr); |
| 1185 | let wchars = core::slice::from_raw_parts(w_ptr, len); |
| 1186 | #[cfg(windows)] |
| 1187 | { |
| 1188 | use rustpython_common::wtf8::Wtf8Buf; |
| 1189 | let wide: Vec<u16> = wchars.to_vec(); |
| 1190 | let wtf8 = Wtf8Buf::from_wide(&wide); |
| 1191 | return Ok(vm.ctx.new_str(wtf8).into()); |
| 1192 | } |
| 1193 | #[cfg(not(windows))] |
| 1194 | { |
| 1195 | #[allow( |
| 1196 | clippy::useless_conversion, |
| 1197 | reason = "wchar_t is i32 on some platforms and u32 on others" |
| 1198 | )] |
| 1199 | let s: String = wchars |
| 1200 | .iter() |
| 1201 | .filter_map(|&c| u32::try_from(c).ok().and_then(char::from_u32)) |
no test coverage detected