Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error types #7

Merged
merged 4 commits into from
Dec 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "identified_vec"
version = "0.1.3"
version = "0.1.4"
edition = "2021"
authors = ["Alexander Cyon <[email protected]>"]
description = "Like HashSet but retaining INSERTION order and without `Hash` requirement on the Element type."
Expand All @@ -15,7 +15,6 @@ serde = ["dep:serde"]
id_prim = []

[dependencies]
anyerror = "0.1.12"
serde = { version = "1.0.193", optional = true }
thiserror = "1.0.50"

Expand Down
11 changes: 11 additions & 0 deletions src/identifiable_trait.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
use std::fmt::Debug;
use std::hash::Hash;

/// The `Identifiable` trait allows you to use the
/// `IdentifiedVecOf<User> instead of the more verbose
/// `IdentifiedVec<SomeUserID, User>` but also allows you to
/// skip the `id_of_element: fn(&Element) -> ID` closure when
/// initializing a new identified vec.
pub trait Identifiable {
/// The type that your `Element` will use as its globally unique and stable ID,
/// must impl `Hash` since it is used as a key in `IdentifiedVecOf`'s internal
/// `HashMap`. Must impl `Clone` since we need to be able to clone it as a key
type ID: Eq + Hash + Clone + Debug;

/// Return `Element`'s globally unique and stable ID, used to uniquely identify
/// the `Element` in the `IdentifiedVecOf` collection of elements.
fn id(&self) -> Self::ID;
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@
//! ```
//! extern crate identified_vec;
//! use identified_vec::{IdentifiedVec, IdentifiedVecOf, Identifiable};
//!
//! // closure which plucks out an ID from an element.
//! let numbers = IdentifiedVec::<u32, u32>::new_identifying_element(|e| *e);
//! ```

Expand Down
2 changes: 1 addition & 1 deletion src/serde_error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[cfg(feature = "serde")]
#[derive(thiserror::Error, Debug, Clone)]
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)]
pub enum IdentifiedVecOfSerdeFailure {
#[error("Duplicate element at offset {0}")]
DuplicateElementsAtIndex(usize),
Expand Down
40 changes: 28 additions & 12 deletions src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ use std::collections::HashMap;
use std::fmt::{Debug, Display};
use std::hash::{Hash, Hasher};

use anyerror::AnyError;

/// Representation of a choice in a conflict resolution
/// where two elements with the same ID exists, if `ChooseFirst`,
/// is specified the first/current/existing value will be used, but
Expand Down Expand Up @@ -236,11 +234,11 @@ where
/// implements high-quality hashing.
#[cfg(not(tarpaulin_include))] // false negative
#[inline]
pub fn new_from_iter_try_uniquing_ids_with<I>(
pub fn try_from_iter_select_unique_ids_with<E, I>(
elements: I,
id_of_element: fn(&Element) -> ID,
combine: fn((usize, &Element, &Element)) -> Result<ConflictResolutionChoice, AnyError>,
) -> Result<Self, AnyError>
combine: fn((usize, &Element, &Element)) -> Result<ConflictResolutionChoice, E>,
) -> Result<Self, E>
where
I: IntoIterator<Item = Element>,
{
Expand Down Expand Up @@ -294,7 +292,7 @@ where
/// implements high-quality hashing.
#[cfg(not(tarpaulin_include))] // false negative
#[inline]
pub fn new_from_iter_uniquing_ids_with<I>(
pub fn from_iter_select_unique_ids_with<I>(
elements: I,
id_of_element: fn(&Element) -> ID,
combine: fn((usize, &Element, &Element)) -> ConflictResolutionChoice,
Expand Down Expand Up @@ -406,16 +404,16 @@ where
self.elements.get_mut(id)
}

/// A read-only collection view for the elements contained in this array, as a `Vec<Elements>`.
/// A read-only collection of references to the elements contained in this array, as a `Vec<&Elements>`.
///
/// N.B. that this method is not constant time.
///
/// If `Element` implements `Clone` you can use `self.items()` which returns a `Vec<Element>`, of cloned elements.
///
/// - Complexity: O(n)
#[inline]
pub fn elements(&self) -> Vec<&Element> {
let mut elements_ordered = Vec::<&Element>::new();
for id in &self.order {
elements_ordered.push(self.elements.get(id).expect("element"));
}
elements_ordered
self.iter().collect()
}

/// Returns `true` if the `identified_vec` contains the `element.`
Expand Down Expand Up @@ -443,6 +441,24 @@ where
}
}

impl<ID, Element> IdentifiedVec<ID, Element>
where
Element: Clone,
ID: Eq + Hash + Clone + Debug,
{
/// A read-only collection of clones of the elements contained in this array, as a `Vec<Elements>`.
///
/// N.B. that this method is not constant time.
///
/// Use `self.elements()` if you are looking for a collection of references.
///
/// - Complexity: O(n)
#[inline]
pub fn items(&self) -> Vec<Element> {
self.iter().map(|e| e.clone()).collect()
}
}

/// An iterator over the items of an `IdentifiedVec`.
pub struct IdentifiedVecIterator<'a, ID, Element>
where
Expand Down
30 changes: 19 additions & 11 deletions src/vec_of.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use anyerror::AnyError;
use std::collections::HashMap;

#[cfg(feature = "serde")]
use std::fmt::Debug;

#[cfg(feature = "serde")]
Expand All @@ -15,6 +16,15 @@ use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
///////////////////////
/// IdentifiedVecOf ///
///////////////////////

/// A type alias for `IdentifiedVec<Element::ID, Element>`, this is the
/// preferred and most powerful collection type of this crate, requires
/// that your `Element`s impl the `Identifiable` trait. Using this collection
/// allows you to skip passing the `id_of_element: fn(&Element) -> ID` closure
/// which you otherwise need to pass when initializing an `IdentifiedVec`. Using
/// `IdentifiedVecOf` together with feature "serde" also gives serde
/// serialization/deserialization as if it were a `Vec<Element>`, given that
/// `Element` implements serde serialization/deserialization of course.
pub type IdentifiedVecOf<Element> = IdentifiedVec<<Element as Identifiable>::ID, Element>;

//////////////////////////////////////////////
Expand Down Expand Up @@ -73,14 +83,14 @@ where
/// - Complexity: Expected O(*n*) on average, where *n* is the count of elements, if `ID`
/// implements high-quality hashing.
#[inline]
pub fn new_from_iter_try_uniquing_with<I>(
pub fn try_from_iter_select_unique_with<E, I>(
elements: I,
combine: fn((usize, &Element, &Element)) -> Result<ConflictResolutionChoice, AnyError>,
) -> Result<Self, AnyError>
combine: fn((usize, &Element, &Element)) -> Result<ConflictResolutionChoice, E>,
) -> Result<Self, E>
where
I: IntoIterator<Item = Element>,
{
Self::new_from_iter_try_uniquing_ids_with(elements, |e| e.id(), combine)
Self::try_from_iter_select_unique_ids_with(elements, |e| e.id(), combine)
}

/// Creates a new `identified_vec` from the elements in the given sequence, using a combining closure to
Expand All @@ -99,14 +109,14 @@ where
/// - Complexity: Expected O(*n*) on average, where *n* is the count of elements, if `ID`
/// implements high-quality hashing.
#[inline]
pub fn new_from_iter_uniquing_with<I>(
pub fn from_iter_select_unique_with<I>(
elements: I,
combine: fn((usize, &Element, &Element)) -> ConflictResolutionChoice,
) -> Self
where
I: IntoIterator<Item = Element>,
{
Self::new_from_iter_uniquing_ids_with(elements, |e| e.id(), combine)
Self::from_iter_select_unique_ids_with(elements, |e| e.id(), combine)
}
}

Expand Down Expand Up @@ -136,10 +146,8 @@ where
deserializer: D,
) -> Result<IdentifiedVecOf<Element>, D::Error> {
let elements = Vec::<Element>::deserialize(deserializer)?;
IdentifiedVecOf::<Element>::new_from_iter_try_uniquing_with(elements, |(idx, _, _)| {
Err(AnyError::new(
&IdentifiedVecOfSerdeFailure::DuplicateElementsAtIndex(idx),
))
IdentifiedVecOf::<Element>::try_from_iter_select_unique_with(elements, |(idx, _, _)| {
Err(IdentifiedVecOfSerdeFailure::DuplicateElementsAtIndex(idx))
})
.map_err(de::Error::custom)
}
Expand Down
Loading
Loading