From df93e2406ab87aa6dcd6e24d5a50bf3dcc55914c Mon Sep 17 00:00:00 2001 From: lambdalemon Date: Mon, 1 Jun 2026 15:07:38 -0400 Subject: [PATCH 1/7] added a flake --- flake.lock | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..c9f0802 --- /dev/null +++ b/flake.lock @@ -0,0 +1,82 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1780246643, + "narHash": "sha256-4T1KWX7xWGQMs9hNZ24IOY3aYOi8D6+5WtkNRBSttB8=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "3109eaae18e09d0b8aef23dc2579e7d94b8d4b4e", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1780284119, + "narHash": "sha256-y2wR4Mk6D/N1ID4FZa2oUMStCUxyIoRzmgOOpLzoWmo=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "51390d0bfca0a68a8c337d215a4bbeddc2ca616e", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..0da360e --- /dev/null +++ b/flake.nix @@ -0,0 +1,85 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = inputs @ { self, nixpkgs, flake-utils, rust-overlay, ... }: + flake-utils.lib.eachDefaultSystem ( + system: let + overlays = [ (import rust-overlay) ]; + pkgs = import nixpkgs { inherit system overlays; }; + in { + devShells.default = with pkgs; mkShell rec { + buildInputs = [ + (rust-bin.nightly.latest.minimal.override { + extensions = [ "clippy" "rust-analyzer" "rust-docs" "rust-src" "miri" ]; + }) + # We use nightly rustfmt features. + (rust-bin.selectLatestNightlyWith (toolchain: toolchain.rustfmt)) + + # Vulkan dependencies + shaderc + spirv-tools + vulkan-loader + vulkan-tools + vulkan-tools-lunarg + vulkan-validation-layers + vulkan-extension-layer + + # winit dependencies + libxkbcommon + wayland + xorg.libX11 + xorg.libXcursor + xorg.libXi + xorg.libXrandr + SDL2 + + clang + libclang + glibc.dev + + valgrind + gdb + + feh + ]; + + LD_LIBRARY_PATH = lib.makeLibraryPath buildInputs; + SHADERC_LIB_DIR = lib.makeLibraryPath [ shaderc ]; + VK_LAYER_PATH = "${vulkan-validation-layers}/share/vulkan/explicit_layer.d"; + }; + devShells.CI = with pkgs; mkShell rec { + buildInputs = [ + (rust-bin.stable.latest.minimal.override { + extensions = [ "clippy" ]; + # Windows CI unfortunately needs to cross-compile from within WSL because Nix doesn't + # work on Windows. + targets = [ "x86_64-pc-windows-msvc" ]; + }) + # We use nightly rustfmt features. + (rust-bin.selectLatestNightlyWith (toolchain: toolchain.rustfmt)) + + # Vulkan dependencies + shaderc + + # winit dependencies + libxkbcommon + wayland + xorg.libX11 + xorg.libXcursor + xorg.libXi + xorg.libXrandr + ]; + + LD_LIBRARY_PATH = lib.makeLibraryPath buildInputs; + SHADERC_LIB_DIR = lib.makeLibraryPath [ shaderc ]; + }; + } + ); +} From 7cd9a4f5024c1e7f7cf0a5fd339ce484f0ce92e2 Mon Sep 17 00:00:00 2001 From: lambdalemon Date: Mon, 1 Jun 2026 15:28:54 -0400 Subject: [PATCH 2/7] fixed all of the errors --- Cargo.toml | 7 ++- src/diplopia.rs | 115 ++++++++++++++++++++++++++++++++++++++++++++++++ src/diplopie.rs | 113 ----------------------------------------------- src/iter.rs | 8 ++-- src/lib.rs | 22 +++------ src/map.rs | 20 +++++---- src/serde.rs | 3 +- 7 files changed, 146 insertions(+), 142 deletions(-) create mode 100644 src/diplopia.rs delete mode 100644 src/diplopie.rs diff --git a/Cargo.toml b/Cargo.toml index cbdb0ae..b46a8ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,9 @@ name = "sicht" version = "0.1.0" edition = "2021" +[feature] +serde = ["dep:serde", "dep:serde_derive"] + [dependencies] -serde = { version = "1.0.217", features = ["derive"] } -serde_derive = "1.0.217" +serde = { optional = true, version = "1.0.217", features = ["derive"] } +serde_derive = { optional = true, version = "1.0.217" } diff --git a/src/diplopia.rs b/src/diplopia.rs new file mode 100644 index 0000000..c1fd570 --- /dev/null +++ b/src/diplopia.rs @@ -0,0 +1,115 @@ +use std::borrow::Borrow; +use std::cmp::PartialEq; +use std::collections::btree_map::Iter; +use std::collections::BTreeMap; +use std::fmt::{Debug, Formatter}; + +/// Named after +/// Also see +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct Diplopia +where + K: Ord + Clone, + V: Ord + Clone, +{ + od: BTreeMap, + os: BTreeMap, +} + +impl Diplopia +where + K: Ord + Clone, + V: Ord + Clone, +{ + #[must_use] + pub fn init(map: BTreeMap) -> Self { + let os = map.iter().map(|(k, v)| (v.clone(), k.clone())).collect(); + Self { od: map, os } + } + + pub fn get(&self, key: &K) -> Option<&V> + where + K: Borrow, + { + self.get_od(key) + } + + pub fn get_od(&self, key: &K) -> Option<&V> { + self.od.get(key) + } + + pub fn get_os(&self, value: &V) -> Option<&K> { + self.os.get(value) + } + + pub fn insert(&mut self, key: K, value: V) { + self.od.insert(key.clone(), value.clone()); + self.os.insert(value, key); + } + + #[allow(clippy::iter_without_into_iter)] + pub fn iter(&self) -> Iter<'_, K, V> { + self.od.iter() + } + + pub fn generate_from_iter(iter: impl Iterator) -> Self { + let (od, os) = iter.fold( + (BTreeMap::default(), BTreeMap::default()), + |(mut normal, mut reverse), (item, coitem)| { + normal.insert(item.clone(), coitem.clone()); + reverse.insert(coitem, item); + (normal, reverse) + }, + ); + + Self { od, os } + } +} + +impl Debug for Diplopia +where + K: Ord + Clone + Debug, + V: Ord + Clone + Debug, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_map().entries(self.iter()).finish() + } +} + +impl Default for Diplopia +where + K: Ord + Clone, + V: Ord + Clone, +{ + fn default() -> Self { + Self { + od: BTreeMap::default(), + os: BTreeMap::default(), + } + } +} + +impl FromIterator<(K, V)> for Diplopia +where + K: Ord + Clone, + V: Ord + Clone, +{ + fn from_iter>(iter: I) -> Self { + Self::generate_from_iter(iter.into_iter()) + } +} + +impl Extend<(K, V)> for Diplopia +where + K: Ord + Clone, + V: Ord + Clone, +{ + fn extend(&mut self, iter: I) + where + I: IntoIterator, + { + iter.into_iter().for_each(move |(k, v)| { + self.insert(k, v); + }); + } +} diff --git a/src/diplopie.rs b/src/diplopie.rs deleted file mode 100644 index 386f8f2..0000000 --- a/src/diplopie.rs +++ /dev/null @@ -1,113 +0,0 @@ -use std::borrow::Borrow; -use std::cmp::PartialEq; -use std::collections::btree_map::Iter; -use std::collections::BTreeMap; -use std::fmt::{Debug, Formatter}; - -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Diplopie -where - K: Ord + Clone, - O: Ord + Clone, -{ - bild: BTreeMap, - urbild: BTreeMap, -} - -impl Diplopie -where - K: Ord + Clone, - O: Ord + Clone, -{ - #[must_use] - pub fn init(map: BTreeMap) -> Self { - let urbild = map.iter().map(|(k, o)| (o.clone(), k.clone())).collect(); - Self { bild: map, urbild } - } - - pub fn get(&self, key: &K) -> Option<&O> - where - K: Borrow, - { - self.get_bild(key) - } - - pub fn get_bild(&self, bild: &K) -> Option<&O> { - self.bild.get(bild) - } - - pub fn get_urbild(&self, urbild: &O) -> Option<&K> { - self.urbild.get(urbild) - } - - pub fn insert(&mut self, bild: K, urbild: O) { - self.bild.insert(bild.clone(), urbild.clone()); - self.urbild.insert(urbild, bild); - } - - #[allow(clippy::iter_without_into_iter)] - pub fn iter(&self) -> Iter<'_, K, O> { - self.bild.iter() - } - - pub fn generate_from_iter(iter: impl Iterator) -> Self { - let (bild, urbild) = iter.fold( - (BTreeMap::default(), BTreeMap::default()), - |(mut bild, mut urbild), (item, coitem)| { - bild.insert(item.clone(), coitem.clone()); - urbild.insert(coitem, item); - (bild, urbild) - }, - ); - - Self { bild, urbild } - } -} - -impl Debug for Diplopie -where - K: Ord + Clone + Debug, - O: Ord + Clone + Debug, -{ - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_map().entries(self.iter()).finish() - } -} - -impl Default for Diplopie -where - K: Ord + Clone, - O: Ord + Clone, -{ - fn default() -> Self { - Self { - bild: BTreeMap::default(), - urbild: BTreeMap::default(), - } - } -} - -impl FromIterator<(K, O)> for Diplopie -where - K: Ord + Clone, - O: Ord + Clone, -{ - fn from_iter>(iter: I) -> Self { - Self::generate_from_iter(iter.into_iter()) - } -} - -impl Extend<(K, O)> for Diplopie -where - K: Ord + Clone, - O: Ord + Clone, -{ - fn extend(&mut self, iter: I) - where - I: IntoIterator, - { - iter.into_iter().for_each(move |(k, v)| { - self.insert(k, v); - }); - } -} diff --git a/src/iter.rs b/src/iter.rs index 12d641e..c515f88 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -1,11 +1,11 @@ -use crate::{Diplopie, SichtMap}; +use crate::{Diplopia, SichtMap}; use std::collections::btree_map::{BTreeMap, Iter}; impl<'a, K, O, V> IntoIterator for &'a SichtMap where K: Ord + Clone + 'a, O: Ord + Clone + 'a, - V: 'a, + V: Ord + 'a, { type Item = (&'a K, &'a V); type IntoIter = Iter<'a, K, V>; @@ -19,6 +19,7 @@ impl FromIterator<(K, O, V)> for SichtMap where K: Ord + Clone, O: Ord + Clone, + V: Ord, { fn from_iter>(iter: I) -> Self { iter.into_iter() @@ -31,9 +32,10 @@ impl FromIterator<((K, V), (K, O))> for SichtMap where K: Ord + Clone, O: Ord + Clone, + V: Ord, { fn from_iter>(iter: I) -> Self { - let (map, lookup): (BTreeMap, Diplopie) = iter.into_iter().unzip(); + let (map, lookup): (BTreeMap, Diplopia) = iter.into_iter().unzip(); Self::with_fields(map, lookup) } } diff --git a/src/lib.rs b/src/lib.rs index 03e8226..f92016a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,21 +1,13 @@ #![deny(rust_2018_idioms)] -#![deny(clippy::pedantic, clippy::dbg_macro)] -#![feature(allocator_api)] -pub mod diplopie; +// #![deny(missing_docs)] +#![allow(clippy::pedantic)] + +pub mod diplopia; pub mod iter; pub mod map; + +#[cfg(feature = "serde")] pub mod serde; -pub use crate::diplopie::Diplopie; +pub use crate::diplopia::Diplopia; pub use crate::map::SichtMap; - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} diff --git a/src/map.rs b/src/map.rs index 04f1d92..d088fa4 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,4 +1,4 @@ -use crate::Diplopie; +use crate::Diplopia; use std::collections::{btree_map::Iter, BTreeMap}; use std::fmt::{Debug, Formatter}; @@ -6,26 +6,28 @@ pub struct SichtMap where K: Ord + Clone, O: Ord + Clone, + V: Ord, { pub(crate) map: BTreeMap, - lookup: Diplopie, + lookup: Diplopia, } impl SichtMap where K: Ord + Clone, O: Ord + Clone, + V: Ord, { #[must_use] pub fn new() -> Self { Self { map: BTreeMap::new(), - lookup: Diplopie::default(), + lookup: Diplopia::default(), } } #[must_use] - pub fn with_fields(map: BTreeMap, lookup: Diplopie) -> Self { + pub fn with_fields(map: BTreeMap, lookup: Diplopia) -> Self { Self { map, lookup } } } @@ -34,6 +36,7 @@ impl SichtMap where K: Ord + Clone, O: Ord + Clone, + V: Ord, { pub fn get(&self, key: &K) -> Option<&V> { self.get_with_base_key(key) @@ -44,7 +47,7 @@ where } pub fn get_with_outer_key(&self, key: &O) -> Option<&V> { - let base_key = self.lookup.get_urbild(key)?; + let base_key = self.lookup.get_os(key)?; self.get_with_base_key(base_key) } @@ -72,7 +75,7 @@ impl Debug for SichtMap where K: Ord + Debug + Clone, O: Ord + Debug + Clone, - V: Debug, + V: Ord + Debug, { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_map().entries(self.iter()).finish() @@ -83,7 +86,7 @@ impl Clone for SichtMap where K: Ord + Clone, O: Ord + Clone, - V: Clone, + V: Clone + Ord, { fn clone(&self) -> Self { Self { @@ -96,8 +99,9 @@ impl Default for SichtMap where K: Ord + Clone, O: Ord + Clone, + V: Ord, { fn default() -> Self { - SichtMap::new() + SichtMap::::new() } } diff --git a/src/serde.rs b/src/serde.rs index 2f7ac6c..6d04981 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -9,7 +9,7 @@ impl<'de, K, O, V> Deserialize<'de> for SichtMap where K: Deserialize<'de> + Ord + Clone + 'de, O: Deserialize<'de> + Ord + Clone + 'de, - V: Deserialize<'de>, + V: Deserialize<'de> + Ord, { fn deserialize(deserializer: D) -> Result where @@ -33,6 +33,7 @@ where where K: Clone + Ord, O: Clone + Ord, + V: Ord, { type Value = SichtMap; From 5af2bdd4823b2ee0b063086defb926e8ddb291de Mon Sep 17 00:00:00 2001 From: lambdalemon Date: Mon, 1 Jun 2026 15:31:50 -0400 Subject: [PATCH 3/7] minor fixes --- src/diplopia.rs | 2 ++ src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/diplopia.rs b/src/diplopia.rs index c1fd570..0e31a4a 100644 --- a/src/diplopia.rs +++ b/src/diplopia.rs @@ -5,6 +5,7 @@ use std::collections::BTreeMap; use std::fmt::{Debug, Formatter}; /// Named after +/// /// Also see #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Diplopia @@ -27,6 +28,7 @@ where Self { od: map, os } } + #[inline] pub fn get(&self, key: &K) -> Option<&V> where K: Borrow, diff --git a/src/lib.rs b/src/lib.rs index f92016a..01c8358 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ #![allow(clippy::pedantic)] pub mod diplopia; -pub mod iter; +mod iter; pub mod map; #[cfg(feature = "serde")] From bb1998f189989e4f54448cc958981653e794bb2d Mon Sep 17 00:00:00 2001 From: lambdalemon Date: Thu, 4 Jun 2026 22:41:01 -0400 Subject: [PATCH 4/7] add birelational map --- Cargo.toml | 3 +- src/birelational_map.rs | 151 ++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/serde.rs | 4 +- tests/birelational_map.rs | 43 +++++++++++ 5 files changed, 199 insertions(+), 3 deletions(-) create mode 100644 src/birelational_map.rs create mode 100644 tests/birelational_map.rs diff --git a/Cargo.toml b/Cargo.toml index b46a8ac..ab1ea9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,10 @@ name = "sicht" version = "0.1.0" edition = "2021" -[feature] +[features] serde = ["dep:serde", "dep:serde_derive"] [dependencies] serde = { optional = true, version = "1.0.217", features = ["derive"] } serde_derive = { optional = true, version = "1.0.217" } +slotmap = "1.1.1" diff --git a/src/birelational_map.rs b/src/birelational_map.rs new file mode 100644 index 0000000..73ddd60 --- /dev/null +++ b/src/birelational_map.rs @@ -0,0 +1,151 @@ +use std::{collections::HashMap, hash::Hash}; + +use slotmap::{DefaultKey, SlotMap}; + +pub trait BirelationalId { + type Id; + + fn get_id(&self) -> Self::Id; +} + +impl BirelationalId for usize { + type Id = usize; + + fn get_id(&self) -> Self::Id { + *self + } +} + +// A <= AID => [B] +// B <= BID => [A] + +// Entity <= EntityId => [Component] +// Component <= ComponentId => [Entity] + +pub struct BirelationalMap +where + K: BirelationalId, + V: BirelationalId, + K::Id: Hash + Eq + PartialEq, + V::Id: Hash + Eq + PartialEq, +{ + keys: SlotMap, + values: SlotMap, + keys_map: HashMap)>, + values_map: HashMap)>, +} + +impl BirelationalMap +where + K: BirelationalId, + V: BirelationalId, + K::Id: Hash + Eq + PartialEq, + V::Id: Hash + Eq + PartialEq, +{ + pub fn new() -> Self { + Self { + keys: SlotMap::new(), + values: SlotMap::new(), + keys_map: HashMap::new(), + values_map: HashMap::new(), + } + } + + pub fn get(&mut self, key: K) -> Option> { + self.keys_map + .get(&key.get_id())? + .1 + .iter() + .map(|x| self.values.get(*x)) + .collect() + } + + pub fn get_value(&mut self, value: V) -> Option> { + self.values_map + .get(&value.get_id())? + .1 + .iter() + .map(|x| self.keys.get(*x)) + .collect() + } + + pub fn insert(&mut self, key: K, value: V) { + let (key_id, value_id) = (key.get_id(), value.get_id()); + let key_exists = self.keys_map.contains_key(&key_id); + let value_exists = self.values_map.contains_key(&value_id); + + match (key_exists, value_exists) { + (true, true) => { + let key_idx = self.keys_map.get(&key_id).unwrap().0; + let value_idx = self.values_map.get(&value_id).unwrap().0; + + let (_, values) = self.keys_map.get_mut(&key_id).unwrap(); + if !values.contains(&value_idx) { + values.push(value_idx); + } + + let (_, keys) = self.values_map.get_mut(&value_id).unwrap(); + if !keys.contains(&key_idx) { + keys.push(key_idx); + } + } + (true, false) => { + let key_idx = self.keys_map.get(&key_id).unwrap().0; + let value_idx = self.values.insert(value); + + let (_, values) = self.keys_map.get_mut(&key_id).unwrap(); + values.push(value_idx); + self.values_map.insert(value_id, (value_idx, vec![key_idx])); + } + (false, true) => { + let value_idx = self.values_map.get(&value_id).unwrap().0; + let key_idx = self.keys.insert(key); + + self.keys_map.insert(key_id, (key_idx, vec![value_idx])); + let (_, keys) = self.values_map.get_mut(&value_id).unwrap(); + keys.push(key_idx); + } + (false, false) => { + let key_idx = self.keys.insert(key); + let value_idx = self.values.insert(value); + + self.keys_map.insert(key_id, (key_idx, vec![value_idx])); + self.values_map.insert(value_id, (value_idx, vec![key_idx])); + } + } + } + + pub fn remove(&mut self, key: K, value: V) + where + for<'a> &'a V: PartialEq, + for<'a> &'a K: PartialEq, + { + if let Some((_, items)) = self.keys_map.get_mut(&key.get_id()) { + let taken_items = std::mem::take(items); + *items = taken_items + .into_iter() + .filter(|x| self.values.get(*x) != Some(&value)) + .collect(); + } + + if let Some((_, items)) = self.values_map.get_mut(&value.get_id()) { + let taken_items = std::mem::take(items); + *items = taken_items + .into_iter() + .filter(|x| self.keys.get(*x) != Some(&key)) + .collect(); + } + } +} + +impl Default for BirelationalMap +where + K: BirelationalId, + V: BirelationalId, + K::Id: Hash + Eq + PartialEq, + V::Id: Hash + Eq + PartialEq, +{ + fn default() -> Self { + Self::new() + } +} diff --git a/src/lib.rs b/src/lib.rs index 01c8358..f340434 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ // #![deny(missing_docs)] #![allow(clippy::pedantic)] +pub mod birelational_map; pub mod diplopia; mod iter; pub mod map; diff --git a/src/serde.rs b/src/serde.rs index 6d04981..5f44f9f 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -121,7 +121,7 @@ pub trait Pair { pub struct Error {} impl Display for Error { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + fn fmt(&self, _f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { todo!() } } @@ -129,7 +129,7 @@ impl Display for Error { impl std::error::Error for Error {} impl serde::de::Error for Error { - fn custom(msg: T) -> Self + fn custom(_msg: T) -> Self where T: Display, { diff --git a/tests/birelational_map.rs b/tests/birelational_map.rs new file mode 100644 index 0000000..d10124b --- /dev/null +++ b/tests/birelational_map.rs @@ -0,0 +1,43 @@ +use sicht::birelational_map::BirelationalMap; + +#[test] +pub fn inserting() { + let mut map = BirelationalMap::new(); + map.insert(10, 20); + + let value = *map.get(10).unwrap()[0]; + assert_eq!(value, 20); + + let key = *map.get_value(20).unwrap()[0]; + assert_eq!(key, 10); +} + +#[test] +pub fn inserting_twice() { + let mut map = BirelationalMap::new(); + map.insert(10, 20); + map.insert(10, 30); + + let value = map.get(10).unwrap(); + assert_eq!(*value[0], 20); + assert_eq!(*value[1], 30); + + let key = *map.get_value(30).unwrap()[0]; + assert_eq!(key, 10); + + let key = *map.get_value(20).unwrap()[0]; + assert_eq!(key, 10); +} + +#[test] +pub fn removal() { + let mut map = BirelationalMap::new(); + map.insert(10, 20); + map.insert(10, 30); + + map.remove(10, 30); + + let values = map.get(10).unwrap(); + assert_eq!(values.len(), 1); + assert_eq!(*values[0], 20); +} From 39a91c38dce0ae5b3d14e160d2798520f4d43f78 Mon Sep 17 00:00:00 2001 From: lambdalemon Date: Fri, 5 Jun 2026 14:21:33 -0400 Subject: [PATCH 5/7] renamed the thing --- src/{diplopia.rs => diplopie.rs} | 13 +++++++------ src/iter.rs | 4 ++-- src/lib.rs | 4 ++-- src/map.rs | 8 ++++---- 4 files changed, 15 insertions(+), 14 deletions(-) rename src/{diplopia.rs => diplopie.rs} (90%) diff --git a/src/diplopia.rs b/src/diplopie.rs similarity index 90% rename from src/diplopia.rs rename to src/diplopie.rs index 0e31a4a..8733fb3 100644 --- a/src/diplopia.rs +++ b/src/diplopie.rs @@ -5,10 +5,11 @@ use std::collections::BTreeMap; use std::fmt::{Debug, Formatter}; /// Named after +/// An instance of Diplopia /// /// Also see #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Diplopia +pub struct Diplopie where K: Ord + Clone, V: Ord + Clone, @@ -17,7 +18,7 @@ where os: BTreeMap, } -impl Diplopia +impl Diplopie where K: Ord + Clone, V: Ord + Clone, @@ -68,7 +69,7 @@ where } } -impl Debug for Diplopia +impl Debug for Diplopie where K: Ord + Clone + Debug, V: Ord + Clone + Debug, @@ -78,7 +79,7 @@ where } } -impl Default for Diplopia +impl Default for Diplopie where K: Ord + Clone, V: Ord + Clone, @@ -91,7 +92,7 @@ where } } -impl FromIterator<(K, V)> for Diplopia +impl FromIterator<(K, V)> for Diplopie where K: Ord + Clone, V: Ord + Clone, @@ -101,7 +102,7 @@ where } } -impl Extend<(K, V)> for Diplopia +impl Extend<(K, V)> for Diplopie where K: Ord + Clone, V: Ord + Clone, diff --git a/src/iter.rs b/src/iter.rs index c515f88..5cc19a9 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -1,4 +1,4 @@ -use crate::{Diplopia, SichtMap}; +use crate::{Diplopie, SichtMap}; use std::collections::btree_map::{BTreeMap, Iter}; impl<'a, K, O, V> IntoIterator for &'a SichtMap @@ -35,7 +35,7 @@ where V: Ord, { fn from_iter>(iter: I) -> Self { - let (map, lookup): (BTreeMap, Diplopia) = iter.into_iter().unzip(); + let (map, lookup): (BTreeMap, Diplopie) = iter.into_iter().unzip(); Self::with_fields(map, lookup) } } diff --git a/src/lib.rs b/src/lib.rs index f340434..2586027 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,12 +3,12 @@ #![allow(clippy::pedantic)] pub mod birelational_map; -pub mod diplopia; +pub mod diplopie; mod iter; pub mod map; #[cfg(feature = "serde")] pub mod serde; -pub use crate::diplopia::Diplopia; +pub use crate::diplopie::Diplopie; pub use crate::map::SichtMap; diff --git a/src/map.rs b/src/map.rs index d088fa4..f865583 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,4 +1,4 @@ -use crate::Diplopia; +use crate::Diplopie; use std::collections::{btree_map::Iter, BTreeMap}; use std::fmt::{Debug, Formatter}; @@ -9,7 +9,7 @@ where V: Ord, { pub(crate) map: BTreeMap, - lookup: Diplopia, + lookup: Diplopie, } impl SichtMap @@ -22,12 +22,12 @@ where pub fn new() -> Self { Self { map: BTreeMap::new(), - lookup: Diplopia::default(), + lookup: Diplopie::default(), } } #[must_use] - pub fn with_fields(map: BTreeMap, lookup: Diplopia) -> Self { + pub fn with_fields(map: BTreeMap, lookup: Diplopie) -> Self { Self { map, lookup } } } From 73433313373d152bb12c17c8febd7acd9b3e6db2 Mon Sep 17 00:00:00 2001 From: lambdalemon Date: Fri, 5 Jun 2026 14:28:16 -0400 Subject: [PATCH 6/7] dylan said remove this --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 2586027..90683d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,5 @@ #![deny(rust_2018_idioms)] // #![deny(missing_docs)] -#![allow(clippy::pedantic)] pub mod birelational_map; pub mod diplopie; From 77cb95f9472d4f4c97654019aa8030d76ec33c84 Mon Sep 17 00:00:00 2001 From: lambdalemon Date: Fri, 5 Jun 2026 14:34:31 -0400 Subject: [PATCH 7/7] V is O for OtherKey now.. --- src/diplopie.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/diplopie.rs b/src/diplopie.rs index 8733fb3..7264790 100644 --- a/src/diplopie.rs +++ b/src/diplopie.rs @@ -9,53 +9,53 @@ use std::fmt::{Debug, Formatter}; /// /// Also see #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Diplopie +pub struct Diplopie where K: Ord + Clone, - V: Ord + Clone, + O: Ord + Clone, { - od: BTreeMap, - os: BTreeMap, + od: BTreeMap, + os: BTreeMap, } -impl Diplopie +impl Diplopie where K: Ord + Clone, - V: Ord + Clone, + O: Ord + Clone, { #[must_use] - pub fn init(map: BTreeMap) -> Self { + pub fn init(map: BTreeMap) -> Self { let os = map.iter().map(|(k, v)| (v.clone(), k.clone())).collect(); Self { od: map, os } } #[inline] - pub fn get(&self, key: &K) -> Option<&V> + pub fn get(&self, key: &K) -> Option<&O> where K: Borrow, { self.get_od(key) } - pub fn get_od(&self, key: &K) -> Option<&V> { + pub fn get_od(&self, key: &K) -> Option<&O> { self.od.get(key) } - pub fn get_os(&self, value: &V) -> Option<&K> { + pub fn get_os(&self, value: &O) -> Option<&K> { self.os.get(value) } - pub fn insert(&mut self, key: K, value: V) { + pub fn insert(&mut self, key: K, value: O) { self.od.insert(key.clone(), value.clone()); self.os.insert(value, key); } #[allow(clippy::iter_without_into_iter)] - pub fn iter(&self) -> Iter<'_, K, V> { + pub fn iter(&self) -> Iter<'_, K, O> { self.od.iter() } - pub fn generate_from_iter(iter: impl Iterator) -> Self { + pub fn generate_from_iter(iter: impl Iterator) -> Self { let (od, os) = iter.fold( (BTreeMap::default(), BTreeMap::default()), |(mut normal, mut reverse), (item, coitem)| {