Как работает преобразование примитивного str через несколько «как» приведений? - PullRequest
0 голосов
/ 23 января 2019

Вот что я нашел в исходном коде Rust .Мне трудно понять &mut *(self as *mut str as *mut [u8]) и self as *const str as *const u8.

Это двухэтапное преобразование?Сначала преобразуйте в *mut str или *const str, затем в *mut [u8] или *const u8?

#[stable(feature = "str_mut_extras", since = "1.20.0")]
#[inline(always)]
pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
    &mut *(self as *mut str as *mut [u8])
}
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub const fn as_ptr(&self) -> *const u8 {
    self as *const str as *const u8
}

1 Ответ

0 голосов
/ 23 января 2019

В Rust оператор as позволяет конвертировать один шаг за раз.

Есть несколько разрешенных преобразований, таких как:

  • &T до *const T,
  • &mut T до *mut T,
  • *mut T - *mut U (в ожидании некоторых условий для T и U),
  • ...

Однако, хотя вы можете перейти с &mut T до *mut T до *mut U, дважды используя as, вы не можете перейти непосредственно с &mut T до *mut U; и потому, что компилятору и людям было бы трудно понять промежуточные шаги.


Итак, что это за последовательность преобразования?

  • Переход от ссылки к указателю: типичный &T до *const T или вариант mut.
  • Переход от указателя к str к указателю на [u8]: типичные *const T до *const U для адекватных T и U. str фактически имеет то же представление, что и [u8], но допустимо только подмножество значений (правильные значения UTF-8).

Интересно отметить, что одно безопасно, а другое нет:

  • Поскольку все str равны [u8], преобразование из *str в *[u8] всегда безопасно.
  • Однако, выставление &mut [u8] позволяет разбить инварианты внутри str, и поэтому as_bytes_mut равно unsafe.
...