evil mass commit

please stop doing thisssss
This commit is contained in:
Emilia Allison 2025-01-04 19:22:53 -05:00
parent ce0e1f2743
commit d296854580
Signed by: emilia
GPG Key ID: 05D5D1107E5100A1
9 changed files with 378 additions and 85 deletions

56
Cargo.lock generated
View File

@ -18,6 +18,16 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046"
[[package]]
name = "accesskit"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3d3b8f9bae46a948369bc4a03e815d4ed6d616bd00de4051133a5019dc31c5a"
dependencies = [
"enumn",
"serde",
]
[[package]]
name = "addr2line"
version = "0.24.2"
@ -42,6 +52,7 @@ dependencies = [
"cfg-if",
"getrandom",
"once_cell",
"serde",
"version_check",
"zerocopy",
]
@ -215,6 +226,12 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "base64"
version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "base64"
version = "0.22.1"
@ -256,6 +273,9 @@ name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
dependencies = [
"serde",
]
[[package]]
name = "block"
@ -651,6 +671,7 @@ checksum = "7d72e9c39f6e11a2e922d04a34ec5e7ef522ea3f5a1acfca7a19d16ad5fe50f5"
dependencies = [
"bytemuck",
"emath",
"serde",
]
[[package]]
@ -669,6 +690,7 @@ dependencies = [
"glow 0.16.0",
"glutin",
"glutin-winit",
"home",
"image",
"js-sys",
"log",
@ -679,6 +701,8 @@ dependencies = [
"percent-encoding",
"profiling",
"raw-window-handle",
"ron",
"serde",
"static_assertions",
"wasm-bindgen",
"wasm-bindgen-futures",
@ -695,12 +719,15 @@ version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "252d52224d35be1535d7fd1d6139ce071fb42c9097773e79f7665604f5596b5e"
dependencies = [
"accesskit",
"ahash",
"emath",
"epaint",
"log",
"nohash-hasher",
"profiling",
"ron",
"serde",
]
[[package]]
@ -735,6 +762,7 @@ dependencies = [
"log",
"profiling",
"raw-window-handle",
"serde",
"smithay-clipboard",
"web-time",
"webbrowser",
@ -766,6 +794,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4fe73c1207b864ee40aa0b0c038d6092af1030744678c60188a05c28553515d"
dependencies = [
"bytemuck",
"serde",
]
[[package]]
name = "enumn"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
]
[[package]]
@ -807,6 +847,7 @@ dependencies = [
"nohash-hasher",
"parking_lot",
"profiling",
"serde",
]
[[package]]
@ -2425,6 +2466,7 @@ dependencies = [
"env_logger",
"log",
"plate-tool-lib",
"serde",
]
[[package]]
@ -2693,6 +2735,18 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
[[package]]
name = "ron"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
dependencies = [
"base64 0.21.7",
"bitflags 2.6.0",
"serde",
"serde_derive",
]
[[package]]
name = "rustc-demangle"
version = "0.1.24"
@ -2823,7 +2877,7 @@ version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817"
dependencies = [
"base64",
"base64 0.22.1",
"chrono",
"hex",
"indexmap 1.9.3",

View File

@ -9,7 +9,9 @@ eframe = { version = "0.30", default-features = false, features = [
"default_fonts",
"glow",
"wayland",
"persistence",
]}
log = "0.4"
env_logger = "0.11"
serde = { version = "1.0", features = ["derive"] }

View File

@ -4,76 +4,14 @@ use std::sync::Mutex;
use eframe::egui::{self};
use plate_tool_lib::plate::PlateFormat;
use plate_tool_lib::plate_instances;
use crate::plate::{add_grid, PlateUiState};
use crate::plate::{add_plate, PlateUiState};
use crate::transfer_menu::{self, transfer_menu, CurrentTransferState, TransferMenuState};
#[derive(Default)]
pub struct MainState {
pub source_plates: Vec<plate_tool_lib::plate_instances::PlateInstance>,
pub destination_plates: Vec<plate_tool_lib::plate_instances::PlateInstance>,
pub transfers: Vec<plate_tool_lib::transfer::Transfer>,
}
fn construct_fake_mainstate() -> MainState {
let src_plate: plate_tool_lib::plate_instances::PlateInstance =
plate_instances::PlateInstance::new(
plate_tool_lib::plate::PlateType::Source,
PlateFormat::W96,
"src1".to_owned(),
);
let dest_plate: plate_tool_lib::plate_instances::PlateInstance =
plate_instances::PlateInstance::new(
plate_tool_lib::plate::PlateType::Destination,
PlateFormat::W96,
"dest1".to_owned(),
);
let well_a1 = plate_tool_lib::Well { row: 1, col: 1 };
let well_c3 = plate_tool_lib::Well { row: 3, col: 3 };
let well_a5 = plate_tool_lib::Well { row: 1, col: 5 };
let transfer1_region: plate_tool_lib::transfer_region::TransferRegion =
plate_tool_lib::transfer_region::TransferRegion {
source_plate: src_plate.plate,
source_region: plate_tool_lib::transfer_region::Region::Rect(well_a1, well_c3),
dest_plate: dest_plate.plate,
dest_region: plate_tool_lib::transfer_region::Region::Point(well_a1),
interleave_source: (1, 1),
interleave_dest: (1, 1),
};
let transfer1: plate_tool_lib::transfer::Transfer = plate_tool_lib::transfer::Transfer::new(
src_plate.clone(),
dest_plate.clone(),
transfer1_region,
"Shrimp".to_owned(),
);
let transfer2_region: plate_tool_lib::transfer_region::TransferRegion =
plate_tool_lib::transfer_region::TransferRegion {
source_plate: src_plate.plate,
source_region: plate_tool_lib::transfer_region::Region::Rect(well_a1, well_c3),
dest_plate: dest_plate.plate,
dest_region: plate_tool_lib::transfer_region::Region::Point(well_a5),
interleave_source: (1, 1),
interleave_dest: (2, 2),
};
let transfer2: plate_tool_lib::transfer::Transfer = plate_tool_lib::transfer::Transfer::new(
src_plate.clone(),
dest_plate.clone(),
transfer2_region,
"Shrimp".to_owned(),
);
MainState {
source_plates: vec![src_plate],
destination_plates: vec![dest_plate],
transfers: vec![transfer1, transfer2],
}
}
use crate::main_state::{MainState, construct_fake_mainstate};
use crate::tree::tree;
#[non_exhaustive]
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct MainWindowState {
show_side_panel: bool,
}
@ -87,12 +25,15 @@ impl Default for MainWindowState {
}
#[non_exhaustive]
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct PlateToolEframe {
source_plate_state: Mutex<PlateUiState>,
destination_plate_state: Mutex<PlateUiState>,
main_window_state: MainWindowState,
current_transfer_state: CurrentTransferState,
#[serde(skip)]
transfer_menu_state: TransferMenuState,
#[serde(skip)]
transfer_region_cache: plate_tool_lib::transfer_region_cache::TransferRegionCache,
main_state: MainState,
}
@ -115,21 +56,24 @@ impl Default for PlateToolEframe {
impl PlateToolEframe {
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
// Would load state here
if let Some(storage) = cc.storage {
return eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default();
} else {
let pte: PlateToolEframe = Default::default();
pte.transfer_region_cache.generate_cache(&pte.main_state.transfers);
pte
}
}
}
impl eframe::App for PlateToolEframe {
// State storage
/*
fn save(&mut self, storage: &mut dyn eframe::Storage) {
unimplemented!()
};
*/
log::info!("Saving state");
eframe::set_value(storage, eframe::APP_KEY, self);
}
fn update(&mut self, ctx: &eframe::egui::Context, _frame: &mut eframe::Frame) {
let ordered_ids: Vec<plate_tool_lib::uuid::Uuid> = {
@ -179,6 +123,8 @@ impl eframe::App for PlateToolEframe {
if self.main_window_state.show_side_panel {
egui::SidePanel::left("side_menus").show(ctx, |ui| {
ui.vertical(|ui| {
tree(ui, &mut self.main_state, &self.current_transfer_state);
ui.separator();
transfer_menu(ui, &self.current_transfer_state, &mut self.transfer_menu_state);
});
});
@ -192,7 +138,7 @@ impl eframe::App for PlateToolEframe {
x.y /= 2.0;
x
};
add_grid(
add_plate(
half_height,
PlateFormat::W96,
&self.main_state.transfers,
@ -203,7 +149,7 @@ impl eframe::App for PlateToolEframe {
ui,
self.source_plate_state.lock().unwrap().deref_mut(),
);
add_grid(
add_plate(
half_height,
PlateFormat::W96,
&self.main_state.transfers,

View File

@ -2,4 +2,5 @@ mod app;
mod plate;
mod tree;
mod transfer_menu;
mod main_state;
pub use app::PlateToolEframe;

View File

@ -0,0 +1,123 @@
use plate_tool_lib::plate_instances;
use plate_tool_lib::plate::PlateFormat;
#[derive(Default, Debug, serde::Serialize, serde::Deserialize)]
pub struct MainState {
/// Stores all plates and transfers
///
/// It is not guaranteed that the current_* variables will refer
/// to UUIDs that exist in the lists, only that they did at one time.
/// This can happen if a plate or transfer is removed and set_* is not called.
pub source_plates: Vec<plate_tool_lib::plate_instances::PlateInstance>,
pub destination_plates: Vec<plate_tool_lib::plate_instances::PlateInstance>,
pub transfers: Vec<plate_tool_lib::transfer::Transfer>,
current_source: Option<plate_tool_lib::uuid::Uuid>,
current_destination: Option<plate_tool_lib::uuid::Uuid>,
current_transfer: Option<plate_tool_lib::uuid::Uuid>,
}
impl MainState {
pub fn get_current_source(&self) -> Option<plate_tool_lib::uuid::Uuid> {
self.current_source
}
pub fn get_current_destination(&self) -> Option<plate_tool_lib::uuid::Uuid> {
self.current_destination
}
pub fn get_current_transfer(&self) -> Option<plate_tool_lib::uuid::Uuid> {
self.current_transfer
}
pub fn set_current_source(&mut self, id: plate_tool_lib::uuid::Uuid) -> bool {
if self.source_plates.iter().map(|x| x.get_uuid()).find(|x| *x == id).is_some() {
self.current_source = Some(id);
true
} else {
false
}
}
pub fn set_current_destination(&mut self, id: plate_tool_lib::uuid::Uuid) -> bool {
if self.destination_plates.iter().map(|x| x.get_uuid()).find(|x| *x == id).is_some() {
self.current_destination = Some(id);
true
} else {
false
}
}
pub fn set_current_transfer(&mut self, id: plate_tool_lib::uuid::Uuid) -> bool {
if self.transfers.iter().map(|x| x.get_uuid()).find(|x| *x == id).is_some() {
self.current_transfer = Some(id);
true
} else {
false
}
}
pub fn set_no_current_source(&mut self) {
self.current_source = None;
}
pub fn set_no_current_destination(&mut self) {
self.current_destination = None;
}
pub fn set_no_current_transfer(&mut self) {
self.current_transfer = None;
}
}
pub fn construct_fake_mainstate() -> MainState {
let src_plate: plate_tool_lib::plate_instances::PlateInstance =
plate_instances::PlateInstance::new(
plate_tool_lib::plate::PlateType::Source,
PlateFormat::W96,
"src1".to_owned(),
);
let dest_plate: plate_tool_lib::plate_instances::PlateInstance =
plate_instances::PlateInstance::new(
plate_tool_lib::plate::PlateType::Destination,
PlateFormat::W96,
"dest1".to_owned(),
);
let well_a1 = plate_tool_lib::Well { row: 1, col: 1 };
let well_c3 = plate_tool_lib::Well { row: 3, col: 3 };
let well_a5 = plate_tool_lib::Well { row: 1, col: 5 };
let transfer1_region: plate_tool_lib::transfer_region::TransferRegion =
plate_tool_lib::transfer_region::TransferRegion {
source_plate: src_plate.plate,
source_region: plate_tool_lib::transfer_region::Region::Rect(well_a1, well_c3),
dest_plate: dest_plate.plate,
dest_region: plate_tool_lib::transfer_region::Region::Point(well_a1),
interleave_source: (1, 1),
interleave_dest: (1, 1),
};
let transfer1: plate_tool_lib::transfer::Transfer = plate_tool_lib::transfer::Transfer::new(
src_plate.clone(),
dest_plate.clone(),
transfer1_region,
"Shrimp".to_owned(),
);
let transfer2_region: plate_tool_lib::transfer_region::TransferRegion =
plate_tool_lib::transfer_region::TransferRegion {
source_plate: src_plate.plate,
source_region: plate_tool_lib::transfer_region::Region::Rect(well_a1, well_c3),
dest_plate: dest_plate.plate,
dest_region: plate_tool_lib::transfer_region::Region::Point(well_a5),
interleave_source: (1, 1),
interleave_dest: (2, 2),
};
let transfer2: plate_tool_lib::transfer::Transfer = plate_tool_lib::transfer::Transfer::new(
src_plate.clone(),
dest_plate.clone(),
transfer2_region,
"Shrimp".to_owned(),
);
MainState {
source_plates: vec![src_plate],
destination_plates: vec![dest_plate],
transfers: vec![transfer1, transfer2],
current_source: None,
current_destination: None,
current_transfer: None,
}
}

View File

@ -20,7 +20,7 @@ static STROKE_SELECT: LazyLock<egui::Stroke> =
static STROKE_HOVER: LazyLock<egui::Stroke> =
LazyLock::new(|| egui::Stroke::new(3.0, egui::Color32::from_gray(255)));
#[derive(Clone, Debug)]
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct PlateUiState {
pub drag_start_position: Option<egui::Pos2>,
}
@ -109,8 +109,8 @@ fn calculate_shading_for_wells(
for transfer in transfers {
let cache_result = match plate_type {
plate_tool_lib::plate::PlateType::Source => cache.get_source(transfer),
plate_tool_lib::plate::PlateType::Destination => cache.get_destination(transfer),
plate_tool_lib::plate::PlateType::Source => cache.get_or_calculate_source(transfer),
plate_tool_lib::plate::PlateType::Destination => cache.get_or_calculate_destination(transfer),
};
if let Some(wells) = cache_result {
for well in wells.iter().filter(|x| x.row <= rows && x.col <= columns) {
@ -138,7 +138,7 @@ fn f64_to_color32(x: [f64; 3]) -> Color32 {
Color32::from_rgb(r, g, b)
}
fn add_grid_sub(
fn add_plate_sub(
size: egui::Vec2,
rows: u8,
columns: u8,
@ -226,7 +226,9 @@ fn add_grid_sub(
}
};
let well_infos = {
// Get non-active transfer info
let mut well_infos = calculate_shading_for_wells(rows, columns, transfers, plate_type, ordered_ids, cache);
// Get wells in the current transfer to tack on to well_infos separately
let current_transfer_wells: Option<Box<[(usize,usize)]>> = {
(match plate_type {
@ -351,7 +353,7 @@ fn add_grid_sub(
}
}
pub fn add_grid(
pub fn add_plate(
size: egui::Vec2,
pf: PlateFormat,
transfers: &Vec<plate_tool_lib::transfer::Transfer>,
@ -363,7 +365,7 @@ pub fn add_grid(
state: &mut PlateUiState,
) {
match pf {
PlateFormat::W96 => add_grid_sub(
PlateFormat::W96 => add_plate_sub(
size,
8,
12,
@ -375,7 +377,7 @@ pub fn add_grid(
ui,
state,
),
PlateFormat::W384 => add_grid_sub(
PlateFormat::W384 => add_plate_sub(
size,
16,
24,
@ -387,7 +389,7 @@ pub fn add_grid(
ui,
state,
),
PlateFormat::W1536 => add_grid_sub(
PlateFormat::W1536 => add_plate_sub(
size,
32,
48,

View File

@ -1,9 +1,12 @@
use eframe::egui;
use plate_tool_lib::transfer_region::{Region, TransferRegion};
use plate_tool_lib::transfer_region::{self, Region, TransferRegion};
use std::sync::{Arc, Mutex};
use std::hash::{DefaultHasher, Hash, Hasher};
use crate::main_state::MainState;
pub type CurrentTransferState = Arc<Mutex<CurrentTransferStateInterior>>;
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct CurrentTransferStateInterior {
pub transfer_name: String,
pub source_region: plate_tool_lib::transfer_region::Region,
@ -15,8 +18,11 @@ pub struct CurrentTransferStateInterior {
pub destination_row_interleave: i8,
pub destination_column_interleave: i8,
pub volume: f32,
#[serde(skip)]
transfer_hash: Option<u64>,
#[serde(skip)]
source_wells: Option<Vec<plate_tool_lib::Well>>,
#[serde(skip)]
destination_wells: Option<Vec<plate_tool_lib::Well>>,
}
impl Default for CurrentTransferStateInterior {
@ -96,8 +102,40 @@ impl CurrentTransferStateInterior {
interleave_dest: (self.destination_row_interleave, self.destination_column_interleave),
}
}
pub fn try_new_from_main_state_transfer(ms: &MainState) -> Option<Self> {
let transfer_id = ms.get_current_transfer();
let transfer = ms.transfers.iter().find(|x| Some(x.get_uuid()) == transfer_id);
if let Some(transfer) = transfer {
let volume: f32 = match transfer.volume {
plate_tool_lib::transfer_volume::TransferVolume::Single(x) => x,
plate_tool_lib::transfer_volume::TransferVolume::WellMap(_) => {
log::debug!("COOL BUG: I genuinely don't know when this variant is used and honestly assume that it just never is constructed! Anyway, here's main state:\n{:?}", ms);
unreachable!("It better not!");
},
_ => unreachable!()
};
return Some(Self {
transfer_name: transfer.name.clone(),
source_region: transfer.transfer_region.source_region.clone(),
destination_region: transfer.transfer_region.dest_region.clone(),
source_plate: transfer.transfer_region.source_plate,
destination_plate: transfer.transfer_region.dest_plate,
source_row_interleave: transfer.transfer_region.interleave_source.0,
source_column_interleave: transfer.transfer_region.interleave_source.1,
destination_row_interleave: transfer.transfer_region.interleave_dest.0,
destination_column_interleave: transfer.transfer_region.interleave_dest.1,
volume,
source_wells: None,
destination_wells: None,
transfer_hash: None,
})
}
None
}
}
#[derive(Debug)]
pub struct TransferMenuState {
pub source_region_string: String,
pub destination_region_string: String,

View File

@ -0,0 +1,103 @@
use eframe::egui;
use crate::{main_state::MainState, transfer_menu::{CurrentTransferState, CurrentTransferStateInterior}};
use std::sync::LazyLock;
static SELECT_COLOR: LazyLock<egui::Color32> =
LazyLock::new(|| egui::Color32::from_hex("#aa0000").unwrap());
pub fn tree(ui: &mut egui::Ui, ms: &mut MainState, cts: &CurrentTransferState) {
// Add all source plates
ui.vertical(|ui| {
ui.heading("Source Plates");
let mut new_uuid: Option<plate_tool_lib::uuid::Uuid> = None;
for (name, uuid) in ms.source_plates.iter().map(|x| (&x.name, x.get_uuid())) {
let f = {
let mut f = egui::Frame::none();
if ms.get_current_source().is_some_and(|x| x == uuid) {
f = f.fill(*SELECT_COLOR);
}
f
};
f.show(ui, |ui| {
let r = ui.add(
egui::Label::new(name)
.sense(egui::Sense::click())
.selectable(false),
);
if r.clicked() {
new_uuid = Some(uuid);
log::info!("{:?}", uuid);
}
});
}
if let Some(uuid) = new_uuid {
ms.set_current_source(uuid);
}
});
// Add all destination plates
ui.vertical(|ui| {
ui.heading("Destination Plates");
let mut new_uuid: Option<plate_tool_lib::uuid::Uuid> = None;
for (name, uuid) in ms
.destination_plates
.iter()
.map(|x| (&x.name, x.get_uuid()))
{
let f = {
let mut f = egui::Frame::none();
if ms.get_current_destination().is_some_and(|x| x == uuid) {
f = f.fill(*SELECT_COLOR);
}
f
};
f.show(ui, |ui| {
let r = ui.add(
egui::Label::new(name)
.sense(egui::Sense::click())
.selectable(false),
);
if r.clicked() {
new_uuid = Some(uuid);
log::info!("{:?}", uuid);
}
});
}
if let Some(uuid) = new_uuid {
ms.set_current_destination(uuid);
}
});
// Add all transfers
ui.vertical(|ui| {
ui.heading("Transfers");
let mut new_uuid: Option<plate_tool_lib::uuid::Uuid> = None;
for (name, uuid) in ms.transfers.iter().map(|x| (&x.name, x.get_uuid())) {
let f = {
let mut f = egui::Frame::none();
if ms.get_current_transfer().is_some_and(|x| x == uuid) {
f = f.fill(*SELECT_COLOR);
}
f
};
f.show(ui, |ui| {
let r = ui.add(
egui::Label::new(name)
.sense(egui::Sense::click())
.selectable(false),
);
if r.clicked() {
new_uuid = Some(uuid);
log::info!("{:?}", uuid);
}
});
}
if let Some(uuid) = new_uuid {
ms.set_current_transfer(uuid);
if let Some(new_cts) = CurrentTransferStateInterior::try_new_from_main_state_transfer(ms) {
*cts.lock().unwrap() = new_cts;
}
}
});
}

View File

@ -11,6 +11,11 @@ pub struct TransferRegionCache {
interior: Arc<Mutex<TransferRegionCacheInterior>>,
}
impl Default for TransferRegionCache {
fn default() -> Self {
Self::new()
}
}
impl TransferRegionCache {
pub fn new() -> Self {
TransferRegionCache {
@ -46,10 +51,22 @@ impl TransferRegionCache {
pub fn get_source(&self, tr: &Transfer) -> Option<Arc<[Well]>> {
self.get(tr, true)
}
pub fn get_or_calculate_source(&self, tr: &Transfer) -> Option<Arc<[Well]>> {
if !self.has(tr) {
self.add_overwrite(tr);
}
self.get_source(tr)
}
pub fn get_destination(&self, tr: &Transfer) -> Option<Arc<[Well]>> {
self.get(tr, false)
}
pub fn get_or_calculate_destination(&self, tr: &Transfer) -> Option<Arc<[Well]>> {
if !self.has(tr) {
self.add_overwrite(tr);
}
self.get_destination(tr)
}
fn get(&self, tr: &Transfer, is_source: bool) -> Option<Arc<[Well]>> {
if let Ok(interior) = self.interior.lock() {
@ -63,6 +80,13 @@ impl TransferRegionCache {
None
}
}
fn has(&self, tr: &Transfer) -> bool {
if let Ok(interior) = self.interior.lock() {
interior.cache.contains_key(&tr.get_uuid())
} else {
false
}
}
}
impl Clone for TransferRegionCache {