-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new traits (
MoveRef
, MoveMut
and Move
)
- Loading branch information
Showing
15 changed files
with
230 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/// The result of moving reference out of the value. | ||
pub type Result<T> = core::result::Result<T, MoveError>; | ||
|
||
/// Enum that defines errors which can occur when moving reference | ||
/// out of the value. | ||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | ||
pub enum MoveError { | ||
/// Reference was already moved out of the collection as immutable. | ||
/// It is not allowed to get mutable reference again, but it is allowed to get immutable one. | ||
BorrowedImmutably, | ||
/// Reference was already moved out of the collection as mutable. | ||
/// It is not allowed to get neither immutable nor mutable reference again. | ||
BorrowedMutably, | ||
} | ||
|
||
impl core::fmt::Display for MoveError { | ||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | ||
match self { | ||
Self::BorrowedImmutably => write!(f, "reference was already borrowed immutably"), | ||
Self::BorrowedMutably => write!(f, "reference was already borrowed mutably"), | ||
} | ||
} | ||
} | ||
|
||
#[cfg(feature = "std")] | ||
#[cfg_attr(docsrs, doc(cfg(feature = "std")))] | ||
impl std_crate::error::Error for MoveError {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
pub use self::{ | ||
error::{MoveError, Result}, | ||
move_mut::MoveMut, | ||
move_ref::MoveRef, | ||
r#move::Move, | ||
}; | ||
|
||
mod error; | ||
mod r#move; | ||
mod move_mut; | ||
mod move_ref; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#![allow(clippy::module_inception)] | ||
|
||
use crate::{Many, Result}; | ||
|
||
use super::{MoveMut, MoveRef}; | ||
|
||
/// Trait for containers which hold *different* kinds of reference. | ||
/// | ||
/// Combines [`MoveRef`] and [`MoveMut`] functionality together, | ||
/// allowing to move immutable and mutable references from the same container. | ||
pub trait Move<'owner>: MoveRef<'owner> + MoveMut<'owner> {} | ||
|
||
/// Technically, `Move` is a trait alias to `MoveRef + MoveMut` trait combination. | ||
impl<'owner, T> Move<'owner> for T where T: ?Sized + MoveRef<'owner> + MoveMut<'owner> {} | ||
|
||
/// [`Many`] trait can be implemented for any type which implements [`Move`] trait for any key. | ||
impl<'owner, T, K> Many<'owner, K> for T | ||
where | ||
T: ?Sized + Move<'owner>, | ||
{ | ||
type Ref = <Self as MoveRef<'owner>>::Ref; | ||
|
||
fn try_move_ref(&mut self, _: K) -> Result<Self::Ref> { | ||
MoveRef::move_ref(self) | ||
} | ||
|
||
type Mut = <Self as MoveMut<'owner>>::Mut; | ||
|
||
fn try_move_mut(&mut self, _: K) -> Result<Self::Mut> { | ||
MoveMut::move_mut(self) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
use crate::{Mut, Ref, RefKind}; | ||
|
||
use super::{MoveError, Result}; | ||
|
||
/// Trait for containers which hold *mutable* kind of reference. | ||
/// | ||
/// This trait provides method for retrieving a mutable reference | ||
/// by moving it out of the container to preserve the lifetime of the owner. | ||
/// | ||
/// This is useful when it is needed to get **many** mutable references | ||
/// on different elements of the owner collection. | ||
/// | ||
/// See [crate documentation](crate) for details. | ||
pub trait MoveMut<'owner> { | ||
/// Type of a mutable reference which is being moved out. | ||
type Mut: 'owner; | ||
|
||
/// Tries to move a mutable reference out of the container. | ||
fn move_mut(&mut self) -> Result<Self::Mut>; | ||
} | ||
|
||
/// Mutable reference should be moved out of the [`Option`]. | ||
impl<'owner, T> MoveMut<'owner> for Option<&'owner mut T> | ||
where | ||
T: ?Sized, | ||
{ | ||
type Mut = &'owner mut T; | ||
|
||
fn move_mut(&mut self) -> Result<Self::Mut> { | ||
let unique = self.take().ok_or(MoveError::BorrowedMutably)?; | ||
Ok(unique) | ||
} | ||
} | ||
|
||
/// Mutable reference should be moved out of the optional [`RefKind`] | ||
/// if the kind of reference is mutable. | ||
impl<'owner, T> MoveMut<'owner> for Option<RefKind<'owner, T>> | ||
where | ||
T: ?Sized, | ||
{ | ||
type Mut = &'owner mut T; | ||
|
||
fn move_mut(&mut self) -> Result<Self::Mut> { | ||
let kind = self.take().ok_or(MoveError::BorrowedMutably)?; | ||
|
||
let unique = match kind { | ||
Ref(shared) => { | ||
*self = Some(Ref(shared)); | ||
return Err(MoveError::BorrowedImmutably); | ||
} | ||
Mut(unique) => unique, | ||
}; | ||
Ok(unique) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
use crate::{Ref, RefKind}; | ||
|
||
use super::{MoveError, Result}; | ||
|
||
/// Trait for containers which hold *immutable* kind of reference. | ||
/// | ||
/// This trait provides method for retrieving an immutable reference | ||
/// by moving it out of the container to preserve the lifetime of the owner. | ||
/// | ||
/// This is useful when it is needed to get **many** mutable references | ||
/// on different elements of the owner collection. | ||
/// | ||
/// See [crate documentation](crate) for details. | ||
pub trait MoveRef<'owner> { | ||
/// Type of an immutable reference which is being moved out. | ||
type Ref: 'owner; | ||
|
||
/// Tries to move an immutable reference out of the container. | ||
/// | ||
/// This function can copy an immutable reference or replace mutable reference with immutable one, | ||
/// preserving an immutable reference in the container. | ||
fn move_ref(&mut self) -> Result<Self::Ref>; | ||
} | ||
|
||
/// Immutable reference can be trivially copied. | ||
impl<'owner, T> MoveRef<'owner> for &'owner T | ||
where | ||
T: ?Sized, | ||
{ | ||
type Ref = &'owner T; | ||
|
||
fn move_ref(&mut self) -> Result<Self::Ref> { | ||
Ok(self) | ||
} | ||
} | ||
|
||
/// Optional immutable reference can be trivially copied. | ||
impl<'owner, T> MoveRef<'owner> for Option<&'owner T> | ||
where | ||
T: ?Sized, | ||
{ | ||
type Ref = &'owner T; | ||
|
||
fn move_ref(&mut self) -> Result<Self::Ref> { | ||
let shared = self.ok_or(MoveError::BorrowedImmutably)?; | ||
Ok(shared) | ||
} | ||
} | ||
|
||
/// Mutable reference should be moved out of the [`Option`] | ||
/// and coerced into immutable one. | ||
impl<'owner, T> MoveRef<'owner> for Option<&'owner mut T> | ||
where | ||
T: ?Sized, | ||
{ | ||
type Ref = &'owner T; | ||
|
||
fn move_ref(&mut self) -> Result<Self::Ref> { | ||
let unique = self.take().ok_or(MoveError::BorrowedMutably)?; | ||
Ok(unique) | ||
} | ||
} | ||
|
||
/// To move immutable reference out of the optional [RefKind], | ||
/// it should copy an immutable reference or replace mutable reference with immutable one, | ||
/// preserving an immutable reference in the container. | ||
impl<'owner, T> MoveRef<'owner> for Option<RefKind<'owner, T>> | ||
where | ||
T: ?Sized, | ||
{ | ||
type Ref = &'owner T; | ||
|
||
fn move_ref(&mut self) -> Result<Self::Ref> { | ||
let kind = self.take().ok_or(MoveError::BorrowedMutably)?; | ||
|
||
let shared = kind.into_ref(); | ||
*self = Some(Ref(shared)); | ||
Ok(shared) | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.