Skip to content
This repository has been archived by the owner on Feb 18, 2024. It is now read-only.

Commit

Permalink
Changed debug repr of buffers and bitmaps. (#284)
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgecarleitao authored Aug 13, 2021
1 parent 86edfd6 commit f3667b8
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 10 deletions.
18 changes: 16 additions & 2 deletions src/bitmap/immutable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::sync::Arc;
use crate::{buffer::bytes::Bytes, buffer::MutableBuffer, trusted_len::TrustedLen};

use super::{
utils::{get_bit, get_bit_unchecked, null_count, BitChunk, BitChunks, BitmapIter},
utils::{fmt, get_bit, get_bit_unchecked, null_count, BitChunk, BitChunks, BitmapIter},
MutableBitmap,
};

Expand All @@ -14,7 +14,7 @@ use super::{
/// * memory on this container is sharable across thread boundaries
/// * Cloning [`Bitmap`] is `O(1)`
/// * Slicing [`Bitmap`] is `O(1)`
#[derive(Debug, Clone)]
#[derive(Clone)]
pub struct Bitmap {
bytes: Arc<Bytes<u8>>,
// both are measured in bits. They are used to bound the bitmap to a region of Bytes.
Expand All @@ -24,6 +24,12 @@ pub struct Bitmap {
null_count: usize,
}

impl std::fmt::Debug for Bitmap {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fmt(&self.bytes, self.offset, self.length, f)
}
}

impl Default for Bitmap {
fn default() -> Self {
MutableBitmap::new().into()
Expand Down Expand Up @@ -272,4 +278,12 @@ mod tests {

assert_eq!(6, b.offset());
}

#[test]
fn test_debug() {
let b = Bitmap::from([true, true, false, true, true, true, true, true, true]);
let b = b.slice(2, 7);

assert_eq!(format!("{:?}", b), "[0b111110__, 0b_______1]");
}
}
27 changes: 25 additions & 2 deletions src/bitmap/mutable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::iter::FromIterator;

use crate::{buffer::MutableBuffer, trusted_len::TrustedLen};

use super::utils::{get_bit, null_count, set, set_bit, BitmapIter};
use super::utils::{fmt, get_bit, null_count, set, set_bit, BitmapIter};
use super::Bitmap;

/// A container to store booleans. [`MutableBitmap`] is semantically equivalent
Expand All @@ -12,12 +12,17 @@ use super::Bitmap;
/// The main difference against [`Vec<bool>`] is that a bitmap cannot be represented as `&[bool]`.
/// # Implementation
/// This container is backed by [`MutableBuffer<u8>`].
#[derive(Debug)]
pub struct MutableBitmap {
buffer: MutableBuffer<u8>,
length: usize,
}

impl std::fmt::Debug for MutableBitmap {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fmt(&self.buffer, 0, self.len(), f)
}
}

impl PartialEq for MutableBitmap {
fn eq(&self, other: &Self) -> bool {
self.iter().eq(other.iter())
Expand Down Expand Up @@ -603,4 +608,22 @@ mod tests {
assert_eq!(bitmap.len(), 6);
assert_eq!(bitmap.buffer[0], 0b00101101);
}

#[test]
fn test_debug() {
let mut b = MutableBitmap::new();
assert_eq!(format!("{:?}", b), "[]");
b.push(true);
b.push(false);
assert_eq!(format!("{:?}", b), "[0b______01]");
b.push(false);
b.push(false);
b.push(false);
b.push(false);
b.push(true);
b.push(true);
assert_eq!(format!("{:?}", b), "[0b11000001]");
b.push(true);
assert_eq!(format!("{:?}", b), "[0b11000001, 0b_______1]");
}
}
115 changes: 115 additions & 0 deletions src/bitmap/utils/fmt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use std::fmt::Write;

use super::is_set;

/// Formats `bytes` taking into account an offset and length of the form
pub fn fmt(
bytes: &[u8],
offset: usize,
length: usize,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
assert!(offset < 8);

f.write_char('[')?;
let mut remaining = length;
if remaining == 0 {
f.write_char(']')?;
return Ok(());
}

let first = bytes[0];
let bytes = &bytes[1..];
let empty_before = 8usize.saturating_sub(remaining + offset);
f.write_str("0b")?;
for _ in 0..empty_before {
f.write_char('_')?;
}
let until = std::cmp::min(8, offset + remaining);
for i in offset..until {
if is_set(first, offset + until - 1 - i) {
f.write_char('1')?;
} else {
f.write_char('0')?;
}
}
for _ in 0..offset {
f.write_char('_')?;
}
remaining -= until - offset;

if remaining == 0 {
f.write_char(']')?;
return Ok(());
}

let number_of_bytes = remaining / 8;
for byte in &bytes[..number_of_bytes] {
f.write_str(", ")?;
f.write_fmt(format_args!("{:#010b}", byte))?;
}
remaining -= number_of_bytes * 8;
if remaining == 0 {
f.write_char(']')?;
return Ok(());
}

let last = bytes[std::cmp::min((length + offset + 7) / 8, bytes.len() - 1)];
let remaining = (length + offset) % 8;
f.write_str(", ")?;
f.write_str("0b")?;
for _ in 0..(8 - remaining) {
f.write_char('_')?;
}
for i in 0..remaining {
if is_set(last, remaining - 1 - i) {
f.write_char('1')?;
} else {
f.write_char('0')?;
}
}
f.write_char(']')
}

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

struct A<'a>(&'a [u8], usize, usize);
impl<'a> std::fmt::Debug for A<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fmt(self.0, self.1, self.2, f)
}
}

#[test]
fn test_debug() -> std::fmt::Result {
assert_eq!(format!("{:?}", A(&[1], 0, 0)), "[]");
assert_eq!(format!("{:?}", A(&[0b11000001], 0, 8)), "[0b11000001]");
assert_eq!(
format!("{:?}", A(&[0b11000001, 1], 0, 9)),
"[0b11000001, 0b_______1]"
);
assert_eq!(format!("{:?}", A(&[1], 0, 2)), "[0b______01]");
assert_eq!(format!("{:?}", A(&[1], 1, 2)), "[0b_____00_]");
assert_eq!(format!("{:?}", A(&[1], 2, 2)), "[0b____00__]");
assert_eq!(format!("{:?}", A(&[1], 3, 2)), "[0b___00___]");
assert_eq!(format!("{:?}", A(&[1], 4, 2)), "[0b__00____]");
assert_eq!(format!("{:?}", A(&[1], 5, 2)), "[0b_00_____]");
assert_eq!(format!("{:?}", A(&[1], 6, 2)), "[0b00______]");
assert_eq!(
format!("{:?}", A(&[0b11000001, 1], 1, 9)),
"[0b1100000_, 0b______01]"
);
// extra bytes are ignored
assert_eq!(
format!("{:?}", A(&[0b11000001, 1, 1, 1], 1, 9)),
"[0b1100000_, 0b______01]"
);
assert_eq!(
format!("{:?}", A(&[0b11000001, 1, 1], 2, 16)),
"[0b110000__, 0b00000001, 0b______01]"
);
Ok(())
}
}
2 changes: 2 additions & 0 deletions src/bitmap/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
mod chunk_iterator;
mod fmt;
mod iterator;
mod slice_iterator;
mod zip_validity;

pub use chunk_iterator::{BitChunk, BitChunkIterExact, BitChunks, BitChunksExact};
pub use fmt::fmt;
pub use iterator::BitmapIter;
pub use slice_iterator::SlicesIterator;
pub use zip_validity::{zip_validity, ZipValidity};
Expand Down
20 changes: 16 additions & 4 deletions src/buffer/immutable.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use std::sync::Arc;
use std::{convert::AsRef, usize};
use std::{fmt::Debug, iter::FromIterator};
use std::{convert::AsRef, iter::FromIterator, sync::Arc, usize};

use crate::{trusted_len::TrustedLen, types::NativeType};

Expand All @@ -9,7 +7,7 @@ use super::mutable::MutableBuffer;

/// Buffer represents a contiguous memory region that can be shared with other buffers and across
/// thread boundaries.
#[derive(Clone, PartialEq, Debug)]
#[derive(Clone, PartialEq)]
pub struct Buffer<T: NativeType> {
/// the internal byte buffer.
data: Arc<Bytes<T>>,
Expand All @@ -22,6 +20,12 @@ pub struct Buffer<T: NativeType> {
length: usize,
}

impl<T: NativeType> std::fmt::Debug for Buffer<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&**self, f)
}
}

impl<T: NativeType> Default for Buffer<T> {
#[inline]
fn default() -> Self {
Expand Down Expand Up @@ -226,4 +230,12 @@ mod tests {
let ptr = buffer.as_ptr();
assert_eq!(unsafe { *ptr }, 1);
}

#[test]
fn test_debug() {
let buffer = Buffer::<i32>::from(&[0, 1, 2, 3]);
let buffer = buffer.slice(1, 2);
let a = format!("{:?}", buffer);
assert_eq!(a, "[1, 2]")
}
}
16 changes: 14 additions & 2 deletions src/buffer/mutable.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::iter::FromIterator;
use std::mem::size_of;
use std::ptr::NonNull;
use std::usize;
use std::{fmt::Debug, mem::size_of};

use crate::types::NativeType;
use crate::{alloc, trusted_len::TrustedLen};
Expand Down Expand Up @@ -32,7 +32,6 @@ fn capacity_multiple_of_64<T: NativeType>(capacity: usize) -> usize {
/// let buffer: Buffer<u32> = buffer.into();
/// assert_eq!(buffer.as_slice(), &[256, 1])
/// ```
#[derive(Debug)]
pub struct MutableBuffer<T: NativeType> {
// dangling iff capacity = 0
ptr: NonNull<T>,
Expand All @@ -41,6 +40,12 @@ pub struct MutableBuffer<T: NativeType> {
capacity: usize,
}

impl<T: NativeType> std::fmt::Debug for MutableBuffer<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&**self, f)
}
}

impl<T: NativeType> PartialEq for MutableBuffer<T> {
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
Expand Down Expand Up @@ -770,4 +775,11 @@ mod tests {
let b: Bytes<i32> = b.into();
assert_eq!(b.as_ref(), &[0, 1, 2]);
}

#[test]
fn test_debug() {
let buffer = MutableBuffer::<i32>::from(&[0, 1, 2, 3]);
let a = format!("{:?}", buffer);
assert_eq!(a, "[0, 1, 2, 3]")
}
}

0 comments on commit f3667b8

Please sign in to comment.