Skip to content

Commit

Permalink
feat: initial functionality (#8)
Browse files Browse the repository at this point in the history
* chore: init rust library

* feat: build initial functionality of `FixedIndexVec`

* chore: setup github actions & dependabot

* chore: add clippy & fmt checks to workflow (#2)

* chore: add clippy & fmt checks to workflow

* chore: run ci on all pull requests, regardless of branch

* chore: remove unnecessary conditions from workflow triggers (#3)

* chore: remove unnecessary conditions from workflow triggers

* fix: rename `workflows` directory

* style: run `fmt` & `clippy`

* chore: run workflow for all PRs and core branch merges

* fix: correct workflow file syntax

* chore: rename primary workflow & add badge to readme (#4)

* feat: complete Rust API Checklist before publishing (#5)

* chore: create changelog

* chore: rename `enable-serde` feature to `serde`

* feat: add derives or implementations of common traits

* feat: add `From<HashMap` and `From<BTreeMap>` implementations

* feat: implement `Extend`

* test: validate Send and Sync implementations

* chore: remove redundant `Cargo.toml` metadata

* style: run clippy & fmt

* chore: add `release-plz` workflow (#6)
  • Loading branch information
calteran authored Dec 11, 2023
1 parent b378b11 commit 5f1ce5f
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 9 deletions.
6 changes: 5 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ updates:
interval: "daily"
time: "02:00"
timezone: "Europe/Paris"
open-pull-requests-limit: 10
open-pull-requests-limit: 10
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
31 changes: 31 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: build

on:
pull_request:
push:
branches:
- main
- develop

env:
CARGO_TERM_COLOR: always

jobs:
build_and_test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Run clippy
run: cargo clippy --verbose -- -D warnings

- name: Run fmt
run: cargo fmt -- --check

- name: Build
run: cargo build --verbose

- name: Run tests
run: cargo test --verbose
27 changes: 27 additions & 0 deletions .github/workflows/release-plz.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Release-plz

permissions:
pull-requests: write
contents: write

on:
push:
branches:
- main

jobs:
release-plz:
name: Release-plz
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Run release-plz
uses: MarcoIeni/release-plz-action@v0.5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.0] - 2023-12-11
### Added
- Initial release
- `FixedIndexVec` struct
- `FixedIndexVec::new()` constructor
- `FixedIndexVec::push(value)` method
- `FixedIndexVec::insert(value)` method
- `FixedIndexVec::remove(index)` method
- `FixedIndexVec::get(index)` method
- `FixedIndexVec::iter()` method
- `FixedIndexVec::len()` method
- `FixedIndexVec::is_empty()` method
- `FixedIndexVec::clear()` method
- `FixedIndexVec::reset()` method
- `FixedIndexVec::next_index()` method
- `FixedIndexVec::first()` method
- `FixedIndexVec::last()` method
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
name = "fixed-index-vec"
version = "0.1.0"
edition = "2021"
license-file = "LICENSE"
description = "A vector-like data structure whose indices do not change when elements are removed."
repository = "https://github.com/calteran/fixed-index-vec"
readme = "README.md"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
serde = { version = "1.0", optional = true, features = ["derive"] }

[features]
enable_serde = ["serde"]
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Fixed Index Vector - Rust Crate

[![GitHub Workflow Status](https://github.com/calteran/fixed-index-vec/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/calteran/fixed-index-vec/)

This crate provides `FixedIndexVec`, a Rust collection that functions like an array with immutable indices.
Each value is associated with a unique index upon insertion.
The value can be accessed, inserted, and removed with the index serving as the identifier.
Expand Down Expand Up @@ -47,7 +49,7 @@ use fixed_index_vec::FixedIndexVec;

## Features

- `enable-serde`: Enables serialization and deserialization of `FixedIndexVec` with [Serde](https://serde.rs/). Requires `FixedIndexVec` to contain values that implement `Serialize` and `DeserializeOwned`.
- `serde`: Enables serialization and deserialization of `FixedIndexVec` with [Serde](https://serde.rs/). Requires `FixedIndexVec` to contain values that implement `Serialize` and `DeserializeOwned`.

## Example

Expand Down
59 changes: 55 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![deny(missing_docs)]
#![doc = include_str!("../README.md")]
use std::collections::BTreeMap;
use std::collections::{BTreeMap, HashMap};
use std::fmt::Display;

/// A fixed-size indexed vector that maps indices to values.
///
Expand Down Expand Up @@ -33,13 +34,23 @@ use std::collections::BTreeMap;
/// - The `FixedIndexVec` is backed by a `BTreeMap`, so it is not as fast as a `Vec`.
/// - Index notations are supported (eg. `vec[0]`), however, accessing an index that does not
/// exist will panic.
#[derive(Clone, Debug, Default)]
#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct FixedIndexVec<T> {
map: BTreeMap<usize, T>,
next_index: usize,
}

impl<T: Display> Display for FixedIndexVec<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut s = String::new();
for (i, v) in self.iter() {
s.push_str(&format!("{}: {}\n", i, v));
}
write!(f, "{}", s)
}
}

impl<T> FixedIndexVec<T> {
/// Creates an empty `FixedIndexVec`.
///
Expand Down Expand Up @@ -158,7 +169,7 @@ impl<T> FixedIndexVec<T> {
/// assert_eq!(iter.next(), Some((2, &3)));
/// assert_eq!(iter.next(), None);
/// ```
pub fn iter(&self) -> impl Iterator<Item=(usize, &T)> {
pub fn iter(&self) -> impl Iterator<Item = (usize, &T)> {
self.map.iter().map(|(i, v)| (*i, v))
}

Expand Down Expand Up @@ -302,7 +313,7 @@ impl<T> std::ops::Index<usize> for FixedIndexVec<T> {
}

impl<T> FromIterator<T> for FixedIndexVec<T> {
fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> FixedIndexVec<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> FixedIndexVec<T> {
let mut map = BTreeMap::new();
for (i, v) in iter.into_iter().enumerate() {
map.insert(i, v);
Expand All @@ -314,8 +325,48 @@ impl<T> FromIterator<T> for FixedIndexVec<T> {
}
}

impl<T> Extend<T> for FixedIndexVec<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for v in iter.into_iter() {
self.push(v);
}
}
}

impl<T> From<Vec<T>> for FixedIndexVec<T> {
fn from(vec: Vec<T>) -> FixedIndexVec<T> {
vec.into_iter().collect()
}
}

impl<T, A> From<HashMap<A, T>> for FixedIndexVec<T> {
fn from(map: HashMap<A, T>) -> FixedIndexVec<T> {
map.into_values().collect()
}
}

impl<T, A> From<BTreeMap<A, T>> for FixedIndexVec<T> {
fn from(map: BTreeMap<A, T>) -> FixedIndexVec<T> {
map.into_values().collect()
}
}

#[cfg(test)]
mod tests {
use super::FixedIndexVec;

#[test]
fn test_send() {
fn assert_send<T: Send>() {}
assert_send::<FixedIndexVec<i32>>();
assert_send::<FixedIndexVec<f32>>();
assert_send::<FixedIndexVec<String>>();
}
#[test]
fn test_sync() {
fn assert_sync<T: Sync>() {}
assert_sync::<FixedIndexVec<i32>>();
assert_sync::<FixedIndexVec<f32>>();
assert_sync::<FixedIndexVec<String>>();
}
}

0 comments on commit 5f1ce5f

Please sign in to comment.