use record::DefaultIdAllocator;
use reexport::glib;
use reexport::relm4;
use reexport::log;
use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use relm4::Sender;
use record::Identifiable;
use record::TemporaryIdAllocator;
use crate::DataStore;
use crate::OrderedBackend;
use crate::OrderedStore;
use crate::Replies;
use crate::StoreId;
use crate::StoreMsg;
use crate::StoreViewMsg;
#[derive(Debug)]
pub struct Store<Backend, StoreIdAllocator=DefaultIdAllocator>
where
Backend: crate::Backend,
StoreIdAllocator: TemporaryIdAllocator,
{
id: StoreId<Self>,
backend: Rc<RefCell<Backend>>,
#[allow(clippy::type_complexity)]
connections: Rc<RefCell<HashMap<StoreId<Self>, Sender<StoreViewMsg<Backend::Record>>>>>,
sender: Sender<StoreMsg<Backend::Record>>,
}
impl<Backend, StoreIdAllocator> Store<Backend, StoreIdAllocator>
where
Backend: 'static + crate::Backend,
StoreIdAllocator: 'static + TemporaryIdAllocator,
{
pub fn new(backend: Backend) -> Self {
let (sender, receiver) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
let id = StoreId::new();
let shared_backed = Rc::new(RefCell::new(backend));
let handler_backend = shared_backed.clone();
#[allow(clippy::type_complexity)]
let connections: Rc<RefCell<HashMap<StoreId<Self>, Sender<StoreViewMsg<Backend::Record>>>>> = Rc::new(RefCell::new(HashMap::new()));
let handler_connections = connections.clone();
{
let context = glib::MainContext::default();
receiver.attach(Some(&context), move |msg:StoreMsg<Backend::Record>| {
if let Ok(mut backend) = handler_backend.try_borrow_mut() {
let replies = backend.inbox(msg);
if let Ok(mut connections) = handler_connections.try_borrow_mut() {
let mut to_remove = Vec::<StoreId<Store<Backend, StoreIdAllocator>>>::new();
for (sid,c) in connections.iter() {
for msg in &replies.replies {
if let Err(..) = c.send(msg.clone()) {
to_remove.push(*sid);
break;
}
}
}
for sid in to_remove {
connections.remove(&sid);
}
}
else {
log::warn!("Can't borrow connections. Remember to release leases");
}
}
else {
log::warn!("Can't borrow backend. Remember to release the leases");
}
glib::Continue(true)
});
}
Store {
id,
backend: shared_backed,
sender,
connections,
}
}
pub fn fire_handlers(&self, messages: &[StoreViewMsg<Backend::Record>]) {
if let Ok(mut connections) = self.connections.try_borrow_mut() {
let mut to_remove = Vec::<StoreId<Store<Backend, StoreIdAllocator>>>::new();
for (sid,c) in connections.iter() {
for msg in messages {
if let Err(..) = c.send(msg.clone()) {
to_remove.push(*sid);
break;
}
}
}
for sid in to_remove {
connections.remove(&sid);
}
}
else {
log::warn!("Can't borrow connections. Remember to release leases");
}
}
pub fn backend(&self) -> Rc<RefCell<Backend>> {
self.backend.clone()
}
}
impl<Backend, StoreIdAllocator> Identifiable<Store<Backend, StoreIdAllocator>, StoreIdAllocator::Type> for Store<Backend, StoreIdAllocator>
where
Backend: crate::Backend,
StoreIdAllocator: TemporaryIdAllocator,
{
type Id=StoreId<Self>;
fn get_id(&self) -> Self::Id {
self.id
}
}
impl<Backend, StoreIdAllocator> DataStore for Store<Backend, StoreIdAllocator>
where
Backend: crate::Backend,
StoreIdAllocator: TemporaryIdAllocator,
{
type Allocator = StoreIdAllocator;
type Record = Backend::Record;
type Messages = StoreMsg<Self::Record>;
fn len(&self) -> usize {
let be: &RefCell<Backend> = self.backend.borrow();
be.borrow().len()
}
fn is_empty(&self) -> bool {
let be: &RefCell<Backend> = self.backend.borrow();
be.borrow().is_empty()
}
fn get(&self, id: &record::Id<Self::Record>) -> Option<Self::Record> {
let be: &RefCell<Backend> = self.backend.borrow();
be.borrow().get(id)
}
fn get_range(&self, range: &crate::math::Range) -> Vec<Self::Record> {
let be: &RefCell<Backend> = self.backend.borrow();
be.borrow().get_range(range)
}
fn listen(&self, id: StoreId<Self>, sender: reexport::relm4::Sender<StoreViewMsg<Self::Record>>) {
self.connections.borrow_mut().insert(id, sender);
}
fn unlisten(&self, handler_ref: StoreId<Self>) {
self.connections.borrow_mut().remove(&handler_ref);
}
fn sender(&self) -> Sender<StoreMsg<Self::Record>> {
self.sender.clone()
}
fn send(&self, msg: crate::StoreMsg<Self::Record>) {
self.sender.send(msg).unwrap();
}
}
impl<Backend, OrderBy, StoreIdAllocator> OrderedStore<OrderBy> for Store<Backend, StoreIdAllocator>
where
Backend: 'static + crate::Backend + OrderedBackend<OrderBy>,
StoreIdAllocator: 'static + TemporaryIdAllocator,
{
fn set_order(&self, order: OrderBy) {
let be: &RefCell<Backend> = self.backend.borrow();
let Replies{ replies } = be.borrow_mut().set_order(order);
self.fire_handlers(&replies);
}
}
impl<Backend, StoreIdAllocator> Clone for Store<Backend, StoreIdAllocator>
where
Backend: crate::Backend,
StoreIdAllocator: TemporaryIdAllocator,
{
fn clone(&self) -> Self {
Store{
id: self.id,
backend: self.backend.clone(),
connections: self.connections.clone(),
sender: self.sender.clone(),
}
}
}