OsStr, Path - как реализовано?

Вчера столкнулся с этими трейтами, стало интересно как они реализованы. По сути, это просто обвзяка вокруг стандартного &str. Но не могу понять, как они создаются.
Path::new создаётся всего лишь несколькими приведениями типов

pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
    unsafe { &*(s.as_ref() as *const OsStr as *const Path) }
}

Для OsStr метода new вообще не нашел. Но у него есть какое-то поле типа Slice, которое делает что угодно:

pub struct OsStr {
    inner: Slice
}

Это какая-то магия компилятора, поскольку они в модуле std::ffi?

OsStr и Path это таки не трейты, а обычные структуры.

Нет. В этом же и суть, что это платформозависимые типы, данные которых совсем не факт что могут быть представлены как стандартный str/String (допустим, путь с битым юникодом в str нельзя запихивать, но он может быть именем файла на некоторых платформах).

у него есть какое-то поле типа Slice, которое делает что угодно:

Надо смотреть исходники под конкретную платформу. Например, вот виндовая реализация:

Но не могу понять, как они создаются.

А в чем именно вопрос? Path, как ты указал, создается или на основе ссылки на что-то, представимое как OsStr, или из его “старшего брата” PathBuf.

OsStr аналогично - или на основе ссылки на какие-то данные (pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr), или заимствуется из своего “старшего брата” - OsString.

Да, это уже нашел.

Вопрос в том, что поле inner в Path не инициализируется, а всё конструирование выполняется приведениями типов. И я что-то не вижу реализаций From<> или To<> для этих типов.

По сути, все создание OsStr живет в этих реализациях AsRef:

image

что поле inner в Path не инициализируется, а всё конструирование выполняется приведениями типов

Поскольку структура из одного поля, то адрес этого поля такой же, как у самой структуры. Так что в Path::new сначала через AsRef получается ссылка на OsStr, а потом она просто unsafe’ом приводится к ссылке на Path.

1 лайк

Спасибо! Подзабыл я уже, за время веб-разработки, эти фокусы из C++ :slight_smile: