range-traits-0.3.2/.cargo_vcs_info.json0000644000000001360000000000100134360ustar { "git": { "sha1": "19926504c0387a590f87ddc20c70de03cd3df72d" }, "path_in_vcs": "" }range-traits-0.3.2/.github/workflows/ci.yml000064400000000000000000000031711046102023000167430ustar 00000000000000name: CI on: push: branches: [ main ] pull_request: branches: [ main ] types: - opened - reopened - synchronize - ready_for_review env: CARGO_TERM_COLORS: always jobs: tests: name: Tests runs-on: ubuntu-latest if: ${{ !github.event.pull_request.draft }} steps: - name: Checkout uses: actions/checkout@v2 - name: Install Rust uses: actions-rs/toolchain@v1 with: toolchain: "1.66.0" profile: minimal override: true - name: Build run: cargo build --all-features --verbose - name: Run tests run: cargo test --all-features --verbose rustfmt: name: Formatting runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Install Rust uses: actions-rs/toolchain@v1 with: toolchain: "1.66.0" profile: minimal override: true components: rustfmt - name: Check formatting uses: actions-rs/cargo@v1 with: command: fmt args: --all -- --check clippy: name: Warnings runs-on: ubuntu-latest if: ${{ !github.event.pull_request.draft }} steps: - name: Checkout repository uses: actions/checkout@v2 - name: Install Rust uses: actions-rs/toolchain@v1 with: toolchain: "1.66.0" profile: minimal override: true components: clippy - name: Clippy Check uses: actions-rs/cargo@v1 with: command: clippy args: --all-features -- -D warningsrange-traits-0.3.2/.gitignore000064400000000000000000000000241046102023000142120ustar 00000000000000/target /Cargo.lock range-traits-0.3.2/.rustfmt.toml000064400000000000000000000000201046102023000146750ustar 00000000000000hard_tabs = truerange-traits-0.3.2/Cargo.toml0000644000000016640000000000100114430ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "range-traits" version = "0.3.2" authors = ["Timothée Haudebourg "] description = "Ranges related traits." documentation = "https://docs.rs/range-traits" readme = "README.md" keywords = [ "range", "trait", "datatype", ] categories = ["data-structures"] license = "MIT/Apache-2.0" repository = "https://github.com/timothee-haudebourg/range-traits" [dependencies.ordered-float] version = "3.0.0" optional = true range-traits-0.3.2/Cargo.toml.orig000064400000000000000000000007301046102023000151150ustar 00000000000000[package] name = "range-traits" version = "0.3.2" edition = "2021" authors = ["Timothée Haudebourg "] description = "Ranges related traits." categories = ["data-structures"] keywords = ["range", "trait", "datatype"] repository = "https://github.com/timothee-haudebourg/range-traits" documentation = "https://docs.rs/range-traits" license = "MIT/Apache-2.0" readme = "README.md" [dependencies] ordered-float = { version = "3.0.0", optional = true }range-traits-0.3.2/README.md000064400000000000000000000033051046102023000135060ustar 00000000000000# Range traits [![Build](https://img.shields.io/github/actions/workflow/status/timothee-haudebourg/range-traits/ci.yml?branch=main&style=flat-square)](https://github.com/timothee-haudebourg/range-traits/actions) [![Crate informations](https://img.shields.io/crates/v/range-traits.svg?style=flat-square)](https://crates.io/crates/range-traits) [![License](https://img.shields.io/crates/l/range-traits.svg?style=flat-square)](https://github.com/timothee-haudebourg/range-traits#license) [![Documentation](https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square)](https://docs.rs/range-traits) This library provides utility traits for data types that can be used to define ranges of values. Default implementations exists for primitive numeric types and `char`. The defined traits can help define basic tasks on ranges such as enumerating the elements of the range (`PartialEnum`), measure the size of the range (`Measure`), etc. Its primary use is through the [`btree-range-map`](https://crates.io/crates/btree-range-map) crate that define data-structures indexed by ranges. By implementing the traits defined in here, one can extend the type of ranges supported by `btree-range-map`, without necessarily depending on it. ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. range-traits-0.3.2/README.tpl000064400000000000000000000021041046102023000137010ustar 00000000000000# Range traits [![Build](https://img.shields.io/github/actions/workflow/status/timothee-haudebourg/{{crate}}/ci.yml?branch=main&style=flat-square)](https://github.com/timothee-haudebourg/{{crate}}/actions) [![Crate informations](https://img.shields.io/crates/v/{{crate}}.svg?style=flat-square)](https://crates.io/crates/{{crate}}) [![License](https://img.shields.io/crates/l/{{crate}}.svg?style=flat-square)](https://github.com/timothee-haudebourg/{{crate}}#license) [![Documentation](https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square)](https://docs.rs/{{crate}}) {{readme}} ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.range-traits-0.3.2/src/bounded.rs000064400000000000000000000015421046102023000150050ustar 00000000000000pub trait MaybeBounded: Sized { fn min() -> Option; fn max() -> Option; } pub trait Bounded { fn min() -> Self; fn max() -> Self; } impl MaybeBounded for T { fn min() -> Option { Some(Self::min()) } fn max() -> Option { Some(Self::max()) } } impl Bounded for char { fn min() -> Self { '\0' } fn max() -> Self { char::MAX } } macro_rules! impl_int { ($($ty:ident),*) => { $( impl Bounded for $ty { fn min() -> Self { $ty::MIN } fn max() -> Self { $ty::MAX } } )* }; } impl_int!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); macro_rules! impl_float { ($($ty:ident),*) => { $( impl Bounded for $ty { fn min() -> Self { $ty::NEG_INFINITY } fn max() -> Self { $ty::INFINITY } } )* }; } impl_float!(f32, f64); range-traits-0.3.2/src/enumerable.rs000064400000000000000000000024131046102023000155020ustar 00000000000000use crate::MaybeBounded; /// Type for which instances can be partially enumerated. pub trait PartialEnum: PartialOrd + MaybeBounded { fn pred(&self) -> Option; fn succ(&self) -> Option; } /// Type for which instances can be entirely enumerated. pub trait Enum: PartialOrd + MaybeBounded { fn pred(&self) -> Option; fn succ(&self) -> Option; } impl PartialEnum for T { fn pred(&self) -> Option { self.pred() } fn succ(&self) -> Option { self.succ() } } impl Enum for char { fn pred(&self) -> Option { ('\u{0000}'..*self).next_back() } fn succ(&self) -> Option { // we skip one element since that's the current char, not its successor (*self..='\u{10ffff}').nth(1) } } macro_rules! impl_int { ($($ty:ident),*) => { $( impl Enum for $ty { fn pred(&self) -> Option { self.checked_sub(1) } fn succ(&self) -> Option { self.checked_add(1) } } )* }; } impl_int!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); macro_rules! impl_float { ($($ty:ident),*) => { $( impl PartialEnum for $ty { fn pred(&self) -> Option { None } fn succ(&self) -> Option { None } } )* }; } impl_float!(f32, f64); range-traits-0.3.2/src/generate-measures.rb000075500000000000000000000036441046102023000167700ustar 00000000000000#!/usr/bin/env ruby class Type attr_accessor :size, :name def initialize(signed, size) @signed = signed @size = size if self.signed? then @name = "i#{@size}" else @name = "u#{@size}" end end def min if self.signed? then - self.max else 0 end end def max (1 << self.unsigned_size) - 1 end def signed? @signed end def unsigned_size if self.signed? then @size - 1 else @size end end def to_s self.name end end $types = [ Type.new(false, 8), Type.new(false, 16), Type.new(false, 32), Type.new(false, 64), Type.new(false, 128), Type.new(true, 8), Type.new(true, 16), Type.new(true, 32), Type.new(true, 64), Type.new(true, 128) ] def impl(ty1, ty2, gate = nil) max = [ty2.max - ty1.min, ty1.max - ty2.min].max output_min_size = max.bit_length len_min_size = (max+1).bit_length # the `Len` type must be able to store the total number of elements. len_size = [8, 16, 32, 64, 128].find { |s| s >= len_min_size } intermediate_signed = ty1.signed? || ty2.signed? intermediate_min_size = output_min_size intermediate_min_size += 1 if intermediate_signed intermediate_size = [8, 16, 32, 64, 128].find { |s| s >= intermediate_min_size } unless intermediate_size.nil? || len_size.nil? then intermediate_ty = Type.new(intermediate_signed, intermediate_size) len_ty = Type.new(false, len_size) if ty1 == ty2 then puts gate unless gate.nil? puts "impl_measure!(@refl #{ty1}, #{intermediate_ty}, #{len_ty});" else puts gate unless gate.nil? puts "impl_measure!(@both #{ty1}, #{ty2}, #{intermediate_ty}, #{len_ty});" end end end $types.each do |ty| impl(ty, ty) end $types.combination(2).map do |ty1, ty2| impl(ty1, ty2) end [8, 16, 32, 64].each do |word_size| usize = Type.new(false, word_size) usize.name = "usize" gate = "#[cfg(target_pointer_width=\"#{word_size}\")]" impl(usize, usize, gate) $types.each do |ty| impl(usize, ty, gate) end endrange-traits-0.3.2/src/lib.rs000064400000000000000000000014271046102023000141350ustar 00000000000000//! This library provides utility traits for data types that can be used //! to define ranges of values. Default implementations exists for //! primitive numeric types and `char`. //! The defined traits can help define basic tasks on ranges such as //! enumerating the elements of the range (`PartialEnum`), //! measure the size of the range (`Measure`), etc. //! //! Its primary use is through the [`btree-range-map`](https://crates.io/crates/btree-range-map) crate //! that define data-structures indexed by ranges. //! By implementing the traits defined in here, one can extend the type of //! ranges supported by `btree-range-map`, without necessarily depending on it. #![no_std] mod bounded; mod enumerable; mod measure; pub use bounded::*; pub use enumerable::*; pub use measure::*; range-traits-0.3.2/src/measure.rs000064400000000000000000000154471046102023000150370ustar 00000000000000use core::{ mem, ops::{Add, Sub}, }; /// Distance between singletons. #[allow(clippy::len_without_is_empty)] pub trait Measure { type Len: Default + Add + Sub + PartialEq; /// Returns the length of the given element. fn len(&self) -> Self::Len; /// Returns the distance to the given other element. fn distance(&self, other: &Rhs) -> Self::Len; } impl Measure for char { type Len = u64; fn len(&self) -> u64 { 1 } fn distance(&self, other: &char) -> u64 { let mut a = *self as u64; let mut b = *other as u64; if a > b { mem::swap(&mut a, &mut b); } if (..=0xd7ff).contains(&a) && (0xe000..).contains(&b) { (b - 0xd000 + 1) + (0xd7ff - a) } else { b - a } } } macro_rules! impl_measure { // Measure for type `$ty`. // `$cast` is a type that can handle the subtraction of two elements // without overflowing. // `$len` is a type that can handle the size of the entire domain of `$ty`. (@refl $ty:ty, $cast:ty, $len:ty) => { impl_measure!($ty, $ty, $cast, $len); }; (@both $ty1:ty, $ty2:ty, $cast:ty, $len:ty) => { impl_measure!($ty1, $ty2, $cast, $len); impl_measure!($ty2, $ty1, $cast, $len); }; ($ty1:ty, $ty2:ty, $cast:ty, $len:ty) => { impl Measure<$ty2> for $ty1 { type Len = $len; fn len(&self) -> $len { 1 } fn distance(&self, other: &$ty2) -> $len { let a = *self as $cast; let b = *other as $cast; if a > b { (a - b) as $len } else { (b - a) as $len } } } }; } // All of those are generated by the `generate-measures.rb` script // to avoid mistakes. impl_measure!(@refl u8, u8, u16); impl_measure!(@refl u16, u16, u32); impl_measure!(@refl u32, u32, u64); impl_measure!(@refl u64, u64, u128); impl_measure!(@refl i8, i16, u8); impl_measure!(@refl i16, i32, u16); impl_measure!(@refl i32, i64, u32); impl_measure!(@refl i64, i128, u64); impl_measure!(@both u8, u16, u16, u32); impl_measure!(@both u8, u32, u32, u64); impl_measure!(@both u8, u64, u64, u128); impl_measure!(@both u8, i8, i16, u16); impl_measure!(@both u8, i16, i32, u16); impl_measure!(@both u8, i32, i64, u32); impl_measure!(@both u8, i64, i128, u64); impl_measure!(@both u16, u32, u32, u64); impl_measure!(@both u16, u64, u64, u128); impl_measure!(@both u16, i8, i32, u32); impl_measure!(@both u16, i16, i32, u32); impl_measure!(@both u16, i32, i64, u32); impl_measure!(@both u16, i64, i128, u64); impl_measure!(@both u32, u64, u64, u128); impl_measure!(@both u32, i8, i64, u64); impl_measure!(@both u32, i16, i64, u64); impl_measure!(@both u32, i32, i64, u64); impl_measure!(@both u32, i64, i128, u64); impl_measure!(@both u64, i8, i128, u128); impl_measure!(@both u64, i16, i128, u128); impl_measure!(@both u64, i32, i128, u128); impl_measure!(@both u64, i64, i128, u128); impl_measure!(@both i8, i16, i32, u16); impl_measure!(@both i8, i32, i64, u32); impl_measure!(@both i8, i64, i128, u64); impl_measure!(@both i16, i32, i64, u32); impl_measure!(@both i16, i64, i128, u64); impl_measure!(@both i32, i64, i128, u64); #[cfg(target_pointer_width = "8")] impl_measure!(@refl usize, u8, u16); #[cfg(target_pointer_width = "8")] impl_measure!(@both usize, u8, u8, u16); #[cfg(target_pointer_width = "8")] impl_measure!(@both usize, u16, u16, u32); #[cfg(target_pointer_width = "8")] impl_measure!(@both usize, u32, u32, u64); #[cfg(target_pointer_width = "8")] impl_measure!(@both usize, u64, u64, u128); #[cfg(target_pointer_width = "8")] impl_measure!(@both usize, i8, i16, u16); #[cfg(target_pointer_width = "8")] impl_measure!(@both usize, i16, i32, u16); #[cfg(target_pointer_width = "8")] impl_measure!(@both usize, i32, i64, u32); #[cfg(target_pointer_width = "8")] impl_measure!(@both usize, i64, i128, u64); #[cfg(target_pointer_width = "16")] impl_measure!(@refl usize, u16, u32); #[cfg(target_pointer_width = "16")] impl_measure!(@both usize, u8, u16, u32); #[cfg(target_pointer_width = "16")] impl_measure!(@both usize, u16, u16, u32); #[cfg(target_pointer_width = "16")] impl_measure!(@both usize, u32, u32, u64); #[cfg(target_pointer_width = "16")] impl_measure!(@both usize, u64, u64, u128); #[cfg(target_pointer_width = "16")] impl_measure!(@both usize, i8, i32, u32); #[cfg(target_pointer_width = "16")] impl_measure!(@both usize, i16, i32, u32); #[cfg(target_pointer_width = "16")] impl_measure!(@both usize, i32, i64, u32); #[cfg(target_pointer_width = "16")] impl_measure!(@both usize, i64, i128, u64); #[cfg(target_pointer_width = "32")] impl_measure!(@refl usize, u32, u64); #[cfg(target_pointer_width = "32")] impl_measure!(@both usize, u8, u32, u64); #[cfg(target_pointer_width = "32")] impl_measure!(@both usize, u16, u32, u64); #[cfg(target_pointer_width = "32")] impl_measure!(@both usize, u32, u32, u64); #[cfg(target_pointer_width = "32")] impl_measure!(@both usize, u64, u64, u128); #[cfg(target_pointer_width = "32")] impl_measure!(@both usize, i8, i64, u64); #[cfg(target_pointer_width = "32")] impl_measure!(@both usize, i16, i64, u64); #[cfg(target_pointer_width = "32")] impl_measure!(@both usize, i32, i64, u64); #[cfg(target_pointer_width = "32")] impl_measure!(@both usize, i64, i128, u64); #[cfg(target_pointer_width = "64")] impl_measure!(@refl usize, u64, u128); #[cfg(target_pointer_width = "64")] impl_measure!(@both usize, u8, u64, u128); #[cfg(target_pointer_width = "64")] impl_measure!(@both usize, u16, u64, u128); #[cfg(target_pointer_width = "64")] impl_measure!(@both usize, u32, u64, u128); #[cfg(target_pointer_width = "64")] impl_measure!(@both usize, u64, u64, u128); #[cfg(target_pointer_width = "64")] impl_measure!(@both usize, i8, i128, u128); #[cfg(target_pointer_width = "64")] impl_measure!(@both usize, i16, i128, u128); #[cfg(target_pointer_width = "64")] impl_measure!(@both usize, i32, i128, u128); #[cfg(target_pointer_width = "64")] impl_measure!(@both usize, i64, i128, u128); macro_rules! impl_f_measure { ($ty:ty, $zero:expr, $min:expr, $max:expr) => { impl Measure<$ty> for $ty { type Len = $ty; fn len(&self) -> $ty { $zero } fn distance(&self, other: &$ty) -> $ty { if self.is_infinite() || other.is_infinite() { $max } else { let a = *self as $ty; let b = *other as $ty; if a > b { (a - b) as $ty } else { (b - a) as $ty } } } } }; } impl_f_measure!(f32, 0.0f32, f32::NEG_INFINITY, f32::INFINITY); impl_f_measure!(f64, 0.0f64, f64::NEG_INFINITY, f64::INFINITY); #[cfg(feature = "ordered-float")] mod ordered_float { use super::Measure; use ordered_float::NotNan; impl_f_measure!( NotNan, unsafe { NotNan::new_unchecked(0.0f32) }, unsafe { NotNan::new_unchecked(f32::NEG_INFINITY) }, unsafe { NotNan::new_unchecked(f32::INFINITY) } ); impl_f_measure!( NotNan, unsafe { NotNan::new_unchecked(0.0f64) }, unsafe { NotNan::new_unchecked(f64::NEG_INFINITY) }, unsafe { NotNan::new_unchecked(f64::INFINITY) } ); }