From a32832a515c98c924a62561edbbd813176e6f12f Mon Sep 17 00:00:00 2001 From: Henry Schimke Date: Wed, 24 Aug 2022 17:52:28 -0500 Subject: [PATCH] BitSource --- src/common/BitSource.java | 111 ------------------------------------ src/common/mod.rs | 117 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 111 deletions(-) diff --git a/src/common/BitSource.java b/src/common/BitSource.java index b4d0aaf..e69de29 100755 --- a/src/common/BitSource.java +++ b/src/common/BitSource.java @@ -1,111 +0,0 @@ -/* - * Copyright 2007 ZXing authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.zxing.common; - -/** - *

This provides an easy abstraction to read bits at a time from a sequence of bytes, where the - * number of bits read is not often a multiple of 8.

- * - *

This class is thread-safe but not reentrant -- unless the caller modifies the bytes array - * it passed in, in which case all bets are off.

- * - * @author Sean Owen - */ -public final class BitSource { - - private final byte[] bytes; - private int byteOffset; - private int bitOffset; - - /** - * @param bytes bytes from which this will read bits. Bits will be read from the first byte first. - * Bits are read within a byte from most-significant to least-significant bit. - */ - public BitSource(byte[] bytes) { - this.bytes = bytes; - } - - /** - * @return index of next bit in current byte which would be read by the next call to {@link #readBits(int)}. - */ - public int getBitOffset() { - return bitOffset; - } - - /** - * @return index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}. - */ - public int getByteOffset() { - return byteOffset; - } - - /** - * @param numBits number of bits to read - * @return int representing the bits read. The bits will appear as the least-significant - * bits of the int - * @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available - */ - public int readBits(int numBits) { - if (numBits < 1 || numBits > 32 || numBits > available()) { - throw new IllegalArgumentException(String.valueOf(numBits)); - } - - int result = 0; - - // First, read remainder from current byte - if (bitOffset > 0) { - int bitsLeft = 8 - bitOffset; - int toRead = Math.min(numBits, bitsLeft); - int bitsToNotRead = bitsLeft - toRead; - int mask = (0xFF >> (8 - toRead)) << bitsToNotRead; - result = (bytes[byteOffset] & mask) >> bitsToNotRead; - numBits -= toRead; - bitOffset += toRead; - if (bitOffset == 8) { - bitOffset = 0; - byteOffset++; - } - } - - // Next read whole bytes - if (numBits > 0) { - while (numBits >= 8) { - result = (result << 8) | (bytes[byteOffset] & 0xFF); - byteOffset++; - numBits -= 8; - } - - // Finally read a partial byte - if (numBits > 0) { - int bitsToNotRead = 8 - numBits; - int mask = (0xFF >> bitsToNotRead) << bitsToNotRead; - result = (result << numBits) | ((bytes[byteOffset] & mask) >> bitsToNotRead); - bitOffset += numBits; - } - } - - return result; - } - - /** - * @return number of bits that can be read successfully - */ - public int available() { - return 8 * (bytes.length - byteOffset) - bitOffset; - } - -} diff --git a/src/common/mod.rs b/src/common/mod.rs index 5ee2a03..77b99b8 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1419,3 +1419,120 @@ pub trait ECIInput { fn getECIValue(index: usize) -> u32; fn haveNCharacters(index: usize, n: usize) -> bool; } + +/* + * Copyright 2007 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//package com.google.zxing.common; + +/** + *

This provides an easy abstraction to read bits at a time from a sequence of bytes, where the + * number of bits read is not often a multiple of 8.

+ * + *

This class is thread-safe but not reentrant -- unless the caller modifies the bytes array + * it passed in, in which case all bets are off.

+ * + * @author Sean Owen + */ +pub struct BitSource { + bytes: Vec, + byteOffset: usize, + bitOffset: usize, +} + +impl BitSource { + /** + * @param bytes bytes from which this will read bits. Bits will be read from the first byte first. + * Bits are read within a byte from most-significant to least-significant bit. + */ + pub fn new(bytes: Vec) -> Self { + Self { + bytes, + byteOffset: 0, + bitOffset: 0, + } + } + + /** + * @return index of next bit in current byte which would be read by the next call to {@link #readBits(int)}. + */ + pub fn getBitOffset(&self) -> usize { + return self.bitOffset; + } + + /** + * @return index of next byte in input byte array which would be read by the next call to {@link #readBits(int)}. + */ + pub fn getByteOffset(&self) -> usize { + return self.byteOffset; + } + + /** + * @param numBits number of bits to read + * @return int representing the bits read. The bits will appear as the least-significant + * bits of the int + * @throws IllegalArgumentException if numBits isn't in [1,32] or more than is available + */ + pub fn readBits(&self, numBits: usize) -> Result { + if numBits < 1 || numBits > 32 || numBits > self.available() { + return Err(IllegalArgumentException::new(numBits)); + } + + let result = 0; + + // First, read remainder from current byte + if self.bitOffset > 0 { + let bitsLeft = 8 - self.bitOffset; + let toRead = cmp::min(numBits, bitsLeft); + let bitsToNotRead = bitsLeft - toRead; + let mask = (0xFF >> (8 - toRead)) << bitsToNotRead; + result = (self.bytes[self.byteOffset] & mask) >> bitsToNotRead; + numBits -= toRead; + self.bitOffset += toRead; + if self.bitOffset == 8 { + self.bitOffset = 0; + self.byteOffset += 1; + } + } + + // Next read whole bytes + if numBits > 0 { + while numBits >= 8 { + result = (result << 8) | (self.bytes[self.byteOffset] & 0xFF); + self.byteOffset += 1; + numBits -= 8; + } + + // Finally read a partial byte + if numBits > 0 { + let bitsToNotRead = 8 - numBits; + let mask = (0xFF >> bitsToNotRead) << bitsToNotRead; + result = + (result << numBits) | ((self.bytes[self.byteOffset] & mask) >> bitsToNotRead); + self.bitOffset += numBits; + } + } + + return Ok(result); + } + + /** + * @return number of bits that can be read successfully + */ + pub fn available(&self) -> u32 { + return 8 * (self.bytes.len() - self.byteOffset) - self.bitOffset; + } +}