A structure in the standard library meets my needs, but its fields are private, and the standard library does not provide an appropriate way to initialize it.
I only need a small code snippet from the standard library. How can I avoid including a copy of the entire standard library in my code library?
As a concession, I don't care about the safety of the code.
No, there's no way to access private fields from another crate, even with unsafe code.
Which std type are you working with and why do you need to access its private fields? We might be able to help you figure out an alternative approach using the existing API, or you could open an issue asking for the interface you need to be exposed.
I want to implement an extended Rust style escape sequence encoder. (add more escape sequence)
The structure I need to access is core::char::{EscapeDebug, EscapeDefaultState}, which is an automaton and I want to give it a specific state.
Is it possible? Thank you!
/// An extended version of `escape_debug` that optionally permits escaping
/// Extended Grapheme codepoints, single quotes, and double quotes. This
/// allows us to format characters like nonspacing marks better when they're
/// at the start of a string, and allows escaping single quotes in
/// characters, and double quotes in strings.
#[inline]
pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
let init_state = match self {
'\t' => EscapeDefaultState::Backslash('t'),
'\r' => EscapeDefaultState::Backslash('r'),
'\n' => EscapeDefaultState::Backslash('n'),
'\\' => EscapeDefaultState::Backslash(self),
'"' if args.escape_double_quote => EscapeDefaultState::Backslash(self),
'\'' if args.escape_single_quote => EscapeDefaultState::Backslash(self),
_ if args.escape_grapheme_extended && self.is_grapheme_extended() => {
EscapeDefaultState::Unicode(self.escape_unicode())
}
_ if is_printable(self) => EscapeDefaultState::Char(self),
_ => EscapeDefaultState::Unicode(self.escape_unicode()),
};
EscapeDebug(EscapeDefault { state: init_state })
}
It might be '?' => EscapeDefaultState::Backslash('?') or something else.
You could transmute it to a struct with the same layout, or use pointer arithmetic. But that is very unsafe. At the very least it could break if the std implementation ever changed, and could potentially have undefined behavior.
Unless the struct has some specific #[repr] on it, there's no struct with the same layout, even you copy-paste the std's declaration. It is explicitly stated that there are no guarantees of data layout made, so compiler can freely reorder its fields based on the declaration position, usage pattern, or even pseudo-random to prevent people to rely on unguaranteed implementation detail.
Reproducible builds are also a goal, so a different binary for the same code with the same compiler version (and same flags and same PGO input and and and...) is probably a bug. (But there's still no guarantee that two repr(Rust) structs with the same fields have the same layout within the same compilation, say.)
I don't see how reproducible builds are incompatible with randomized layout.
Just take source, call SHA512 on it and use that to seed random-number generator. Plus "salt" command-line option to make sure different builders would build different binaries.
And yes, it would be nice to have it enabled by default.
Not only this would make sure people wouldn't try dirty tricks, but, more importantly, that's quite nice security measure. Linux kernel does that despite using C, thus it sound logical that Rust, being concerned about security have to do that, too.
Although I'm not sure how high this should prioritized. There are lots of other things which are more important.
Some ISAs encode instructions more compactly when field offsets are small (i.e., 0, 1..3F, etc). An optimizing compiler could make a static or PTO-based assessment of which fields are accessed more frequently and order them in the struct in a way that minimizes i-cache fetches. In such a case it is completely reasonable for the compiler to lay out differently two unrelated structs in the same program that just happen to have the same nominal alignment/size ordering of fields.