devices should only be visible on a data connection

This commit is contained in:
Rachel Powers
2024-04-16 23:32:11 -07:00
parent fdec8c7639
commit 07ff3a167b

View File

@@ -397,6 +397,7 @@ pub enum SlotType {
#[derive(Debug, Serialize, Deserialize)]
pub struct Network {
pub devices: HashSet<u32>,
pub power_only: HashSet<u32>,
pub channels: [f64; 8],
}
@@ -404,6 +405,7 @@ impl Default for Network {
fn default() -> Self {
Network {
devices: HashSet::new(),
power_only: HashSet::new(),
channels: [f64::NAN; 8],
}
}
@@ -416,15 +418,59 @@ pub enum NetworkError {
}
impl Network {
pub fn contains(&self, ids: &[u32]) -> bool {
ids.iter().all(|id| self.devices.contains(id))
pub fn contains(&self, id: &u32) -> bool {
self.devices.contains(id) || self.power_only.contains(id)
}
pub fn add(&mut self, id: u32) -> bool {
pub fn contains_all(&self, ids: &[u32]) -> bool {
ids.iter()
.all(|id| self.contains(id))
}
pub fn contains_data(&self, id: &u32) -> bool {
self.devices.contains(id)
}
pub fn contains_all_data(&self, ids: &[u32]) -> bool {
ids.iter().all(|id| self.contains_data(id))
}
pub fn contains_power(&self, id: &u32) -> bool {
self.power_only.contains(id)
}
pub fn contains_all_power(&self, ids: &[u32]) -> bool {
ids.iter().all(|id| self.contains_power(id))
}
pub fn data_visible(&self, source: &u32) -> Vec<u32> {
if self.contains_data(source) {
self.devices
.iter()
.filter(|id| id != &source)
.copied()
.collect_vec()
} else {
Vec::new()
}
}
pub fn add_data(&mut self, id: u32) -> bool {
self.devices.insert(id)
}
pub fn remove(&mut self, id: u32) -> bool {
pub fn add_power(&mut self, id: u32) -> bool {
self.power_only.insert(id)
}
pub fn remove_all(&mut self, id: u32) -> bool {
self.devices.remove(&id) || self.power_only.remove(&id)
}
pub fn remove_data(&mut self, id: u32) -> bool {
self.devices.remove(&id)
}
pub fn remove_power(&mut self, id: u32) -> bool {
self.devices.remove(&id)
}
@@ -1097,9 +1143,20 @@ impl VM {
};
device.connections.iter().for_each(|conn| {
if let Connection::CableNetwork { net: Some(net), .. } = conn {
if let Connection::CableNetwork {
net: Some(net),
typ,
} = conn
{
if let Some(network) = self.networks.get(net) {
network.borrow_mut().add(device_id);
match typ {
CableConnectionType::Power => {
network.borrow_mut().add_power(device_id);
}
_ => {
network.borrow_mut().add_data(device_id);
}
}
}
}
});
@@ -1318,27 +1375,20 @@ impl VM {
pub fn devices_on_same_network(&self, ids: &[u32]) -> bool {
for net in self.networks.values() {
if net.borrow().contains(ids) {
if net.borrow().contains_all_data(ids) {
return true;
}
}
false
}
/// return a vecter with the device ids the source id can see via it's connected netowrks
/// return a vecter with the device ids the source id can see via it's connected networks
pub fn visible_devices(&self, source: u32) -> Vec<u32> {
self.networks
.values()
.filter_map(|net| {
if net.borrow().contains(&[source]) {
Some(
net.borrow()
.devices
.iter()
.filter(|id| id != &&source)
.copied()
.collect_vec(),
)
if net.borrow().contains_data(&source) {
Some(net.borrow().data_visible(&source))
} else {
None
}
@@ -1386,33 +1436,59 @@ impl VM {
{
// scope this borrow
let connections = &device.borrow().connections;
let Connection::CableNetwork { net, .. } = &connections[connection] else {
let Connection::CableNetwork { net, typ } = &connections[connection] else {
return Err(ICError::NotACableConnection(connection).into());
};
// remove from current network
if let Some(net) = net {
if let Some(network) = self.networks.get(net) {
// if there is no other connection to this network
if connections.clone().iter().enumerate().all(|(index, conn)| {
if let Connection::CableNetwork { net: other_net, .. } = conn {
!(other_net.is_some_and(|id| id == *net) && index != connection)
} else {
true
if connections
.iter()
.filter(|conn| {
matches!(conn, Connection::CableNetwork {
net: Some(other_net),
typ: other_typ
} if other_net == net && (
!matches!(typ, CableConnectionType::Power) ||
matches!(other_typ, CableConnectionType::Data | CableConnectionType::PowerAndData))
)
})
.count()
== 1
{
match typ {
CableConnectionType::Power => {
network.borrow_mut().remove_power(id);
}
_ => {
network.borrow_mut().remove_data(id);
}
}
}) {
network.borrow_mut().remove(id);
}
}
}
}
let mut device_ref = device.borrow_mut();
let connections = &mut device_ref.connections;
let Connection::CableNetwork { ref mut net, .. } = connections[connection] else {
let Connection::CableNetwork {
ref mut net,
ref typ,
} = connections[connection]
else {
return Err(ICError::NotACableConnection(connection).into());
};
if let Some(target_net) = target_net {
if let Some(network) = self.networks.get(&target_net) {
network.borrow_mut().add(id);
match typ {
CableConnectionType::Power => {
network.borrow_mut().add_power(id);
}
_ => {
network.borrow_mut().add_data(id);
}
}
} else {
return Err(VMError::InvalidNetwork(target_net));
}
@@ -1435,7 +1511,7 @@ impl VM {
}
}
}
network.borrow_mut().remove(id);
network.borrow_mut().remove_all(id);
Ok(true)
} else {
Err(VMError::InvalidNetwork(network_id))