Skip to content

Commit 378c97a

Browse files
committed
Simplify flag parsing
1 parent 29d0051 commit 378c97a

File tree

1 file changed

+32
-51
lines changed

1 file changed

+32
-51
lines changed

Diff for: crates/iceberg/src/puffin/metadata.rs

+32-51
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
use std::collections::{HashMap, HashSet};
1919

2020
use bytes::Bytes;
21-
use once_cell::sync::Lazy;
2221
use serde::{Deserialize, Serialize};
2322

2423
use crate::io::{FileRead, InputFile};
@@ -56,44 +55,36 @@ pub(crate) struct BlobMetadata {
5655
pub(crate) properties: HashMap<String, String>,
5756
}
5857

59-
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
58+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
6059
pub(crate) enum Flag {
61-
FooterPayloadCompressed,
60+
FooterPayloadCompressed = 0,
6261
}
6362

64-
#[derive(PartialEq, Eq, Hash)]
65-
pub(crate) struct ByteNumber(pub u8);
66-
67-
#[derive(PartialEq, Eq, Hash)]
68-
pub(crate) struct BitNumber(pub u8);
69-
70-
static FLAGS_BY_BYTE_AND_BIT: Lazy<HashMap<(ByteNumber, BitNumber), Flag>> = Lazy::new(|| {
71-
let mut m = HashMap::new();
72-
m.insert(
73-
(
74-
Flag::FooterPayloadCompressed.byte_number(),
75-
Flag::FooterPayloadCompressed.bit_number(),
76-
),
77-
Flag::FooterPayloadCompressed,
78-
);
79-
m
80-
});
81-
8263
impl Flag {
83-
pub(crate) fn byte_number(&self) -> ByteNumber {
84-
match self {
85-
Flag::FooterPayloadCompressed => ByteNumber(0),
86-
}
64+
pub(crate) fn byte_idx(self) -> u8 {
65+
(self as u8) / 8
8766
}
8867

89-
pub(crate) fn bit_number(&self) -> BitNumber {
90-
match self {
91-
Flag::FooterPayloadCompressed => BitNumber(0),
92-
}
68+
pub(crate) fn bit_idx(self) -> u8 {
69+
(self as u8) % 8
9370
}
9471

95-
fn from(byte_and_bit: &(ByteNumber, BitNumber)) -> Option<Flag> {
96-
FLAGS_BY_BYTE_AND_BIT.get(byte_and_bit).cloned()
72+
fn matches(self, byte_idx: &u8, bit_idx: &u8) -> bool {
73+
&self.byte_idx() == byte_idx && &self.bit_idx() == bit_idx
74+
}
75+
76+
fn from(byte_idx: &u8, bit_idx: &u8) -> Result<Flag> {
77+
if Flag::FooterPayloadCompressed.matches(byte_idx, bit_idx) {
78+
Ok(Flag::FooterPayloadCompressed)
79+
} else {
80+
Err(Error::new(
81+
ErrorKind::DataInvalid,
82+
format!(
83+
"Unknown flag byte {} and bit {} combination",
84+
byte_idx, bit_idx
85+
),
86+
))
87+
}
9788
}
9889
}
9990

@@ -178,35 +169,25 @@ impl FileMetadata {
178169

179170
fn decode_flags(footer_bytes: &[u8]) -> Result<HashSet<Flag>> {
180171
let mut flags = HashSet::new();
181-
for byte_number in 0..FileMetadata::FOOTER_STRUCT_FLAGS_LENGTH {
172+
173+
for byte_idx in 0..FileMetadata::FOOTER_STRUCT_FLAGS_LENGTH {
182174
let byte_offset = footer_bytes.len()
183175
- usize::from(FileMetadata::MAGIC_LENGTH)
184176
- usize::from(FileMetadata::FOOTER_STRUCT_FLAGS_LENGTH)
185-
+ usize::from(byte_number);
177+
+ usize::from(byte_idx);
186178

187-
let mut flag_byte = *footer_bytes.get(byte_offset).ok_or_else(|| {
179+
let flag_byte = *footer_bytes.get(byte_offset).ok_or_else(|| {
188180
Error::new(ErrorKind::DataInvalid, "Index range is out of bounds.")
189181
})?;
190-
let mut bit_number = 0;
191-
while flag_byte != 0 {
192-
if flag_byte & 0x1 != 0 {
193-
match Flag::from(&(ByteNumber(byte_number), BitNumber(bit_number))) {
194-
Some(flag) => flags.insert(flag),
195-
None => {
196-
return Err(Error::new(
197-
ErrorKind::DataInvalid,
198-
format!(
199-
"Unknown flag byte {} and bit {} combination",
200-
byte_number, bit_number
201-
),
202-
))
203-
}
204-
};
182+
183+
for bit_idx in 0..8 {
184+
if ((flag_byte >> bit_idx) & 1) != 0 {
185+
let flag = Flag::from(&byte_idx, &bit_idx)?;
186+
flags.insert(flag);
205187
}
206-
flag_byte >>= 1;
207-
bit_number += 1;
208188
}
209189
}
190+
210191
Ok(flags)
211192
}
212193

0 commit comments

Comments
 (0)