Git Product home page Git Product logo

rust-bit-field's Introduction

bit_field

A simple crate which provides the BitField trait, which provides methods for operating on individual bits and ranges of bits on Rust's integral types.

Documentation

Documentation is available on docs.rs

Usage

[dependencies]
bit_field = "0.10.1"

Example

extern crate bit_field;
use bit_field::BitField;

let mut x: u8 = 0;

x.set_bit(7, true);
assert_eq!(x, 0b1000_0000);

x.set_bits(0..4, 0b1001);
assert_eq!(x, 0b1000_1001);

License

This crate is dual-licensed under MIT or the Apache License (Version 2.0). See LICENSE-APACHE and LICENSE-MIT for details.

rust-bit-field's People

Contributors

benwiederhake avatar ethindp avatar freax13 avatar gabibguti avatar ilayrosenberg avatar imhun avatar kjetilkjeka avatar phil-opp avatar rminderhoud avatar toku-sa-n avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

rust-bit-field's Issues

Should there be benchmarking tests as part of the test suite?

To keep up with improvements and avoid regressions and being surprised with things as #15

@huwsun have already helped out creating some in #15. If the benchmarking tests is desired, perhaps he can help out some more with this issue.

Is it possible to break CI for terrible benches? Is this desired?

"non-standard" bit fields

I have a library for integer types that don't align with bytes. It's called ux. The goal is to conform as close as possible to how the ordinary rust types work (u8, u16, u32, u64, i8, i16, i32, i64).

If BitField was implemented on these types, it would be easy to use types of length 2-63 as bit fields. Is this something that would be interesting?

Renaming and Refactoring

As with all renaming and refactoring, this is of course subjective, but there were a few things which I noticed could be cleaned up a little bit (as breaking changes, though, of course):

  • BitField can be made much more generic and operate on signed-integral types and non-integral types (like slices and vectors of integral values). Doing so neccessitates simplifying the API of BitField a little bit to just have length and the bit operations, and then specializing the implementation for unsigned integers, signed integers, and slices/vectors seperately.

  • Having a length field pollutes the namespace somewhat by not being sufficiently descriptive; maybe bit_length? zero and one also do so, but removing them and specializing the implementation as the above point suggests fixes that seperately.

  • Similarly, set_range could be renamed to either set_bits or set_bit_range for clarity's sake.

  • The set functions take the value by mutable reference; it would be nice to see (optional) methods for taking by value, which need only be implemented on the integral types and would allow things like

0u32.set_bit(1, true).set_bit(2, true)
  • The use of a u8 for the index seems arbitrary; it works fine for the existing integral types, but the trait could be made more general by using usize.

Of course, most of this is nitpicking, but if any of it seems mildly appealing I would be more than happy to make any neccessary changes and create a PR.

Feature request: static bit_length() method on types

I'm using the remainder from a big integer to get position in a bit field, like so:

position_in_block = input % RemainderFromInputGetsYouPositionInBitField;

The bit field size is known at compile time, but I want to be able to easily tune it, so I've tried the following (type conversion omitted):

position_in_block = input % PackedBlock::from(0).bit_length();

This works (and I imagine it's very useful in generics), but incurs significant runtime overhead compared to a hardcoded value (this is in a hot codepath and total execution time went up 20% because of it). I've also tried putting the same thing in a constant, but the compiler does not allow that either: "calls in constants are limited to constant functions, struct and enum constructors".

Adding static bit_length() methods on primitive types would be very useful for such use cases. This is the last thing holding me back from completely abstracting the code from the size of the bitfield.

performance issue

Hi,On my mac book pro (8c 16g), the library has a large performance difference compared to the code I manually implement.
I read the library implementation code, logically it should be the same, but why is there such a big difference in performance?
I didn't read all the library code carefully, could you please give me some advice on whether my test method is wrong or the code of the library itself?
rustc 1.27.0-nightly,the bench result:

running 4 tests    
test get_bitfield ... bench:      39,371 ns/iter (+/- 2,489)
test get_trivial  ... bench:         901 ns/iter (+/- 102)
test set_bitfield ... bench:      39,439 ns/iter (+/- 779)
test set_trivial  ... bench:       2,752 ns/iter (+/- 76)

my trivial code and bench code:

#![feature(test)]

extern crate bit_field;

use bit_field::*;

pub trait BitOper {
    fn get_b(&self, idx: usize) -> bool;
    fn set_b(&mut self, idx: usize, val: bool);
    fn toggle(&mut self, idx: usize);
}

impl BitOper for u8 {
    fn set_b(&mut self, idx: usize, val: bool) {
        assert!(idx < 8);
        if val {
            *self |= 1 << idx;
        } else {
            *self &= !(1 << idx);
        }
    }

    fn get_b(&self, idx: usize) -> bool {
        assert!(idx < 8);
        (self & 1 << idx) != 0
    }

    fn toggle(&mut self, idx: usize) {
        assert!(idx < 8);
        *self ^= 1 << idx;
    }
}

impl BitOper for Vec<u8> {
    fn get_b(&self, idx: usize) -> bool {
        self[idx / 8].get_b((idx % 8))
    }

    fn set_b(&mut self, idx: usize, val: bool) {
        self[idx / 8].set_b((idx % 8), val);
    }

    fn toggle(&mut self, idx: usize) {
        self[idx / 8].toggle((idx % 8));
    }
}

extern crate test;

use test::Bencher;

const len: usize = 256;

#[bench]
fn set_bitfield(b: &mut Bencher) {
    let mut v = vec![0u8; len];

    b.iter(|| {
        for i in 0..v.len() * 8 {
            v.as_mut_slice().set_bit(i, true);;
        }
    });
}

#[bench]
fn set_trivial(b: &mut Bencher) {
    let mut v = vec![0u8; len];

    b.iter(|| {
        for i in 0..v.len() * 8 {
            v.set_b(i, true);
        }
    });
}

#[bench]
fn get_bitfield(b: &mut Bencher) {
    let mut v = vec![1u8; len];

    b.iter(|| {
        for i in 0..v.len() * 8 {
            let b = v.as_mut_slice().get_bit(i);
        }
    });
}

#[bench]
fn get_trivial(b: &mut Bencher) {
    let mut v = vec![1u8; len];

    b.iter(|| {
        for i in 0..v.len() * 8 {
            let b = v.get_b(i);
        }
    });
}

Compiling on stable needs some love

error: #[feature] may not be used on the stable release channel [E0554]
 --> /home/marc/.cargo/registry/src/github.com-1ecc6299db9ec823/bit_field-0.5.0/src/lib.rs:1:1
  |>
1 |> #![feature(const_fn)]
  |> ^^^^^^^^^^^^^^^^^^^^^

Pretty please? =)

index of BitField should be usize

@blacksmithgu writes in #4

  • The use of a u8 for the index seems arbitrary; it works fine for the existing integral types, but the trait could be made more general by using usize.

I've been using this crate a while now and everytime I'm compiling I will have some complaints about "expected u8, found usize". And when I fix the errors I still got a lot of "as u8" in the code. I think that BitField would be a lot more ergonomic to use if it were indexed by a usize was the case.

Is the choice of u8 index based upon performance? If so, maybe it would be possible to throw away everything but the lowest 8 bits just inside the function and hope the optimizer handles it? I guess it would need to be inlined as well to hope that anything happens.

implement BitField for slices of BitFields

I feel like it would be nice to have a provided BitField implementation for slices of BitFields.

One issue will be that we can't be guaranteed that all element in the slice have the same size and would have to iterate over n-1 elements when we're setting bits in the n'th element. So setting and getting operations for the slice would be O(n).

This is not ideal since for the most cases all the elements have a constant size and we should be able to do the operations in O(1).

A way for the O(1) access time to be achievable wherever possible could be using the Sized marker trait. This is achieved by doing something in the lines of:

  • A impl<T: BitField + Sized> T or trait BitFieldSized : BitField + Sized would have to be made implementing T::bit_length()
  • Whenever T is Sized+BitField, self.bit_length() would have to return the same as T::bit_length()

Implementing the O(n) algorithm would, of course, be a simpler approach and probably be "good enough".

I will be doing a simple implementation of the BitField trait for [BitField] in my own project. If this is something you desire I'm willing to coordinate it with you for upstreaming?

edit: markdown fixes

Support RangeInclusive

With RangeInclusive landing in Rust 1.26 I think it makes sense to support it. Personally, I think it makes sense to only use RangeInclusive as I have seen people define bit fields (in documentation) typically as inclusive ranges. That said, I am not sure you would want to completely break backwards compatibility, but that is your decision.

Add Security Policy

Adding a Security Policy is important to provide guidance on how users can report potential vulnerabilities and communicate when vulnerabilities will be confirmed, fixed and disclosed to the public.

This is considered a good-practice and recommended by Github and Scorecard.

If you agree, I can open a PR to suggest a Security Policy! We can then work together to communicate how the repo can best handle vulnerability reports.

Additional Context

Hi! I'm Gabriela and I work on behalf of Google and the OpenSSF suggesting supply-chain security changes :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.