Write over the `clockbound_err` memory. This function is the interface between Rust `ClockBoundError` and its C version. The C caller allocates memory and pass a pointer to the `clockbound_err`, which is updated here.
(&mut self, error: ClockBoundError)
| 66 | /// This function is the interface between Rust `ClockBoundError` and its C version. The C |
| 67 | /// caller allocates memory and pass a pointer to the `clockbound_err`, which is updated here. |
| 68 | fn write_error(&mut self, error: ClockBoundError) { |
| 69 | // Kind and errno values are set |
| 70 | self.kind = clockbound_err_kind::from(error.kind); |
| 71 | self.errno = error.errno.0; |
| 72 | |
| 73 | // The detail String has to be converted to a CString, ensuring it is null terminated. |
| 74 | let c_string = match CString::new(error.detail) { |
| 75 | Ok(c_string) => c_string, |
| 76 | Err(_) => { |
| 77 | // Hopefully, we never insert null terminators in the middle of an error message, |
| 78 | // and should never hit that branch. |
| 79 | CString::new("No detail available").unwrap() |
| 80 | } |
| 81 | }; |
| 82 | |
| 83 | // Copy bytes including null terminator if it fits, and truncate if required. |
| 84 | // Possible cast from u8 (bytes) into i8 (c_char) but is platform dependent |
| 85 | let src_ptr = c_string.as_ptr(); |
| 86 | let dst_ptr = self.detail.as_mut_ptr(); |
| 87 | let copy_len = c_string |
| 88 | .as_bytes_with_nul() |
| 89 | .len() |
| 90 | .min(CLOCKBOUND_ERROR_DETAIL_SIZE); |
| 91 | // Safety: rely on the user passing a valid pointer |
| 92 | unsafe { |
| 93 | ptr::copy_nonoverlapping(src_ptr, dst_ptr, copy_len); |
| 94 | } |
| 95 | |
| 96 | // Ensure null termination if we had to truncate. |
| 97 | if copy_len >= CLOCKBOUND_ERROR_DETAIL_SIZE { |
| 98 | self.detail[CLOCKBOUND_ERROR_DETAIL_SIZE - 1] = 0; |
| 99 | } |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | /// The clockbound context given to the caller. |