Struct crate_swap::SwapRequest

source ·
pub struct SwapRequest { /* private fields */ }
Expand description

This struct is used to specify the details of a crate-swapping operation, in which an “old” crate is replaced with a “new” crate that is then used in place of that old crate. The old crate is removed from its old CrateNamespace while the new crate is added to the new CrateNamespace; typically the old and new namespaces are the same.

Important Note: Reexporting Symbols

When swapping out an old crate, the new crate must satisfy all of the dependencies that other crates had on that old crate. However, the swapping procedure will completely remove the old crate and its symbols from its containing CrateNamespace, so it may be useful to re-expose or “mirror” the new crate’s sections as symbols with names that match the relevant sections from the old crate. This satisfies other crates’ dependenices on the old crate while allowing the new crate to exist normally, which means that the new crate’s symbols appear both as those from the new crate itself in addition to those from the old crate that was replaced. To do this, set the reexport_new_symbols_as_old option to true.

However, enabling this option is potentially dangerous, as you must take responsibility for ensuring that the new crate can safely and correctly replace the old crate, and that using the new crate in place of the old crate will not break any other dependent crates. This will necessarily ignore the hashes when matching symbols across the old and new crate, and hashes are how Theseus ensures that different crates and functions are linked to the correct version of each other. However, this does make the swapping operation much simpler to use, because you will likely need to swap far fewer crates at once, and as a convenience bonus, you don’t have to specify the exact versions (hashes) of each crate.

Example of Reexporting Symbols

There exists a function drivers::init::h... in the drivers crate that depends on the function keyboard::init::hABC in the keyboard crate. We call swap_crates() to replace the keyboard crate with a new crate called keyboard_new.

If reexport_new_symbols_as_old is true, the new keyboard_new crate’s function called keyboard_new::init::hDEF will now appear in the namespace’s symbol map twice:

  1. in its normal form keyboard_new::init::hDEF, which is the normal behavior when loading a crate, and
  2. in its reexported form keyboard::init::hABC, which exactly matches the function from the old keyboard crate.

In this way, the single function in the new crate keyboard_new appears twice in the symbol map under different names, allowing it to fulfill dependencies on both the old crate and the new crate. In general, this option is not needed.

Implementations§

source§

impl SwapRequest

source

pub fn new( old_crate_name: Option<&str>, old_namespace: Arc<CrateNamespace>, new_crate_object_file: IntoCrateObjectFile, new_namespace: Option<Arc<CrateNamespace>>, reexport_new_symbols_as_old: bool ) -> Result<SwapRequest, InvalidSwapRequest>

Create a new SwapRequest that, when given to swap_crates(), will swap out the given old crate and replace it with the given new crate, and optionally re-export the new crate’s symbols.

Arguments
  • old_crate_name: the name of the old crate that should be unloaded and removed from the old_namespace. An old_crate_name of None (or an empty string) signifies there is no old crate to be removed, and that only a new crate will be added.

    Note that old_crate_name can be any string prefix, so long as it can uniquely identify a crate object file in the given old_namespace or any of its recursive namespaces. Thus, to be more accurate, it is wise to specify a full crate name with hash, e.g., "my_crate-<hash>".

  • old_namespace: the CrateNamespace that contains the old crate; that old crate and its symbols will be removed from this namespace.

    If old_crate_name is None, then old_namespace should be the same namespace as the this_namespace argument that swap_crates() is invoked with.

  • new_crate_object_file: a type that can be converted into a crate object file. This can either be a direct reference to the file, an absolute PathBuf that points to the file, or a prefix string used to find the file in the new namespace’s directory of crate object files.

  • new_namespace: the CrateNamespace to which the new crate will be loaded and its symbols added. If None, then the new crate will be loaded into the old_namespace, which is a common case for swapping.

  • reexport_new_symbols_as_old: if true, all public symbols the new crate will be reexported in the new_namespace with the same full name those symbols had from the old crate in the old_namespace. See the “Important Note” in the struct-level documentation for more details.

Trait Implementations§

source§

impl Debug for SwapRequest

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl Hash for SwapRequest

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl PartialEq<SwapRequest> for SwapRequest

source§

fn eq(&self, other: &SwapRequest) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Eq for SwapRequest

source§

impl StructuralEq for SwapRequest

source§

impl StructuralPartialEq for SwapRequest

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> CallHasher for Twhere T: Hash + ?Sized,

§

default fn get_hash<H, B>(value: &H, build_hasher: &B) -> u64where H: Hash + ?Sized, B: BuildHasher,

source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.