You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
2.2 KiB
92 lines
2.2 KiB
4 years ago
|
//! Frozen, serialisable state
|
||
|
use super::*;
|
||
|
use futures::prelude::*;
|
||
|
|
||
|
/// An immutable image of `State`.
|
||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||
|
pub struct Freeze
|
||
|
{
|
||
|
users: HashSet<User>,
|
||
|
posts: Vec<(UserID, Post)>,
|
||
|
}
|
||
|
|
||
|
impl Freeze
|
||
|
{
|
||
|
/// Create a `State` from this freeze
|
||
|
///
|
||
|
/// # Notes
|
||
|
/// This clones all post and user data, to perform this operation without cloning, use `into_state`.
|
||
|
pub fn unfreeze(&self) -> State
|
||
|
{
|
||
|
let users: HashMap<UserID, RwLock<User>> = self.users
|
||
|
.iter()
|
||
|
.map(|x| (*x.id(), RwLock::new(x.clone()))).collect();
|
||
|
let mut posts: HashMap<UserID, MaybeVec<RwLock<Post>>> = HashMap::with_capacity(users.len());
|
||
|
|
||
|
for (id, post) in self.posts.iter()
|
||
|
{
|
||
|
posts.entry(*id).or_insert_with(move || MaybeVec::new()).push(RwLock::new(post.clone()));
|
||
|
}
|
||
|
|
||
|
State(Arc::new(Inner{posts: RwLock::new( Posts {
|
||
|
users,
|
||
|
posts
|
||
|
})}))
|
||
|
}
|
||
|
|
||
|
/// Consume into a new `State`.
|
||
|
pub fn into_state(self) -> State
|
||
|
{
|
||
|
State::from_freeze(self)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl State
|
||
|
{
|
||
|
/// Create a serialisable image from this state
|
||
|
pub async fn freeze(&self) -> Freeze
|
||
|
{
|
||
|
let posts = self.0.posts.read().await;
|
||
|
let users: HashSet<User> = {
|
||
|
stream::iter(posts.users.iter())
|
||
|
.then(|(_, x)| async move { x.read().await })
|
||
|
.map(|x| x.clone()).collect().await
|
||
|
};
|
||
|
let posts: Vec<_> = {
|
||
|
stream::iter(posts.posts.iter()
|
||
|
.map(|(x, y)| y.into_iter().map(move |z| (x, z))).flatten())
|
||
|
.then(|x| async move { (x.0, x.1.read().await) })
|
||
|
.map(|(&id, post)| (id, post.clone())).collect().await
|
||
|
};
|
||
|
|
||
|
Freeze {users, posts}
|
||
|
}
|
||
|
|
||
|
/// Create `State` from this image
|
||
|
pub fn from_freeze(freeze: Freeze) -> Self
|
||
|
{
|
||
|
let users: HashMap<UserID, RwLock<User>> = freeze.users
|
||
|
.into_iter()
|
||
|
.map(|x| (*x.id(), RwLock::new(x))).collect();
|
||
|
let mut posts: HashMap<UserID, MaybeVec<RwLock<Post>>> = HashMap::with_capacity(users.len());
|
||
|
|
||
|
for (id, post) in freeze.posts.into_iter()
|
||
|
{
|
||
|
posts.entry(id).or_insert_with(move || MaybeVec::new()).push(RwLock::new(post));
|
||
|
}
|
||
|
|
||
|
Self(Arc::new(Inner{posts: RwLock::new( Posts {
|
||
|
users,
|
||
|
posts
|
||
|
})}))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl From<Freeze> for State
|
||
|
{
|
||
|
#[inline] fn from(from: Freeze) -> Self
|
||
|
{
|
||
|
Self::from_freeze(from)
|
||
|
}
|
||
|
}
|