Updated QrCode.encodeSegments() to throw DataTooLongException - in Java, C++, Python, Rust code. Rust code also changes return types from Option to Result. Updated Java and Rust documentation.

pull/40/head
Project Nayuki 6 years ago
parent 4635e8a8a8
commit 8da8107cc2

@ -74,8 +74,16 @@ QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
dataUsedBits = QrSegment::getTotalBits(segs, version); dataUsedBits = QrSegment::getTotalBits(segs, version);
if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits)
break; // This version number is found to be suitable break; // This version number is found to be suitable
if (version >= maxVersion) // All versions in the range could not fit the given data if (version >= maxVersion) { // All versions in the range could not fit the given data
throw std::length_error("Data too long"); std::ostringstream sb;
if (dataUsedBits == -1)
sb << "Segment too long";
else {
sb << "Data length = " << dataUsedBits << " bits, ";
sb << "Max capacity = " << dataCapacityBits << " bits";
}
throw data_too_long(sb.str());
}
} }
if (dataUsedBits == -1) if (dataUsedBits == -1)
throw std::logic_error("Assertion error"); throw std::logic_error("Assertion error");

@ -64,7 +64,7 @@ public final class QrCode {
* @param ecl the error correction level to use (not {@code null}) (boostable) * @param ecl the error correction level to use (not {@code null}) (boostable)
* @return a QR Code (not {@code null}) representing the text * @return a QR Code (not {@code null}) representing the text
* @throws NullPointerException if the text or error correction level is {@code null} * @throws NullPointerException if the text or error correction level is {@code null}
* @throws IllegalArgumentException if the text fails to fit in the * @throws DataTooLongException if the text fails to fit in the
* largest version QR Code at the ECL, which means it is too long * largest version QR Code at the ECL, which means it is too long
*/ */
public static QrCode encodeText(String text, Ecc ecl) { public static QrCode encodeText(String text, Ecc ecl) {
@ -84,7 +84,7 @@ public final class QrCode {
* @param ecl the error correction level to use (not {@code null}) (boostable) * @param ecl the error correction level to use (not {@code null}) (boostable)
* @return a QR Code (not {@code null}) representing the data * @return a QR Code (not {@code null}) representing the data
* @throws NullPointerException if the data or error correction level is {@code null} * @throws NullPointerException if the data or error correction level is {@code null}
* @throws IllegalArgumentException if the data fails to fit in the * @throws DataTooLongException if the data fails to fit in the
* largest version QR Code at the ECL, which means it is too long * largest version QR Code at the ECL, which means it is too long
*/ */
public static QrCode encodeBinary(byte[] data, Ecc ecl) { public static QrCode encodeBinary(byte[] data, Ecc ecl) {
@ -109,7 +109,7 @@ public final class QrCode {
* @param ecl the error correction level to use (not {@code null}) (boostable) * @param ecl the error correction level to use (not {@code null}) (boostable)
* @return a QR Code (not {@code null}) representing the segments * @return a QR Code (not {@code null}) representing the segments
* @throws NullPointerException if the list of segments, any segment, or the error correction level is {@code null} * @throws NullPointerException if the list of segments, any segment, or the error correction level is {@code null}
* @throws IllegalArgumentException if the segments fail to fit in the * @throws DataTooLongException if the segments fail to fit in the
* largest version QR Code at the ECL, which means they are too long * largest version QR Code at the ECL, which means they are too long
*/ */
public static QrCode encodeSegments(List<QrSegment> segs, Ecc ecl) { public static QrCode encodeSegments(List<QrSegment> segs, Ecc ecl) {
@ -137,8 +137,9 @@ public final class QrCode {
* @return a QR Code (not {@code null}) representing the segments * @return a QR Code (not {@code null}) representing the segments
* @throws NullPointerException if the list of segments, any segment, or the error correction level is {@code null} * @throws NullPointerException if the list of segments, any segment, or the error correction level is {@code null}
* @throws IllegalArgumentException if 1 &#x2264; minVersion &#x2264; maxVersion &#x2264; 40 * @throws IllegalArgumentException if 1 &#x2264; minVersion &#x2264; maxVersion &#x2264; 40
* or &#x2212;1 &#x2264; mask &#x2264; 7 is violated; or if the segments fail to * or &#x2212;1 &#x2264; mask &#x2264; 7 is violated
* fit in the maxVersion QR Code at the ECL, which means they are too long * @throws DataTooLongException if the segments fail to fit in
* the maxVersion QR Code at the ECL, which means they are too long
*/ */
public static QrCode encodeSegments(List<QrSegment> segs, Ecc ecl, int minVersion, int maxVersion, int mask, boolean boostEcl) { public static QrCode encodeSegments(List<QrSegment> segs, Ecc ecl, int minVersion, int maxVersion, int mask, boolean boostEcl) {
Objects.requireNonNull(segs); Objects.requireNonNull(segs);
@ -153,8 +154,12 @@ public final class QrCode {
dataUsedBits = QrSegment.getTotalBits(segs, version); dataUsedBits = QrSegment.getTotalBits(segs, version);
if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits)
break; // This version number is found to be suitable break; // This version number is found to be suitable
if (version >= maxVersion) // All versions in the range could not fit the given data if (version >= maxVersion) { // All versions in the range could not fit the given data
throw new IllegalArgumentException("Data too long"); String msg = "Segment too long";
if (dataUsedBits != -1)
msg = String.format("Data length = %d bits, Max capacity = %d bits", dataUsedBits, dataCapacityBits);
throw new DataTooLongException(msg);
}
} }
assert dataUsedBits != -1; assert dataUsedBits != -1;

@ -124,7 +124,10 @@ class QrCode(object):
if datausedbits is not None and datausedbits <= datacapacitybits: if datausedbits is not None and datausedbits <= datacapacitybits:
break # This version number is found to be suitable break # This version number is found to be suitable
if version >= maxversion: # All versions in the range could not fit the given data if version >= maxversion: # All versions in the range could not fit the given data
raise ValueError("Data too long") msg = "Segment too long"
if datausedbits is not None:
msg = "Data length = {} bits, Max capacity = {} bits".format(datausedbits, datacapacitybits)
raise DataTooLongError(msg)
if datausedbits is None: if datausedbits is None:
raise AssertionError() raise AssertionError()

@ -146,9 +146,9 @@ impl QrCode {
/// QR Code version is automatically chosen for the output. The ECC level of the result may be higher than /// QR Code version is automatically chosen for the output. The ECC level of the result may be higher than
/// the ecl argument if it can be done without increasing the version. /// the ecl argument if it can be done without increasing the version.
/// ///
/// Returns a wrapped `QrCode` if successful, or `None` if the /// Returns a wrapped `QrCode` if successful, or `Err` if the
/// data is too long to fit in any version at the given ECC level. /// data is too long to fit in any version at the given ECC level.
pub fn encode_text(text: &str, ecl: QrCodeEcc) -> Option<Self> { pub fn encode_text(text: &str, ecl: QrCodeEcc) -> Result<Self,DataTooLong> {
let chrs: Vec<char> = text.chars().collect(); let chrs: Vec<char> = text.chars().collect();
let segs: Vec<QrSegment> = QrSegment::make_segments(&chrs); let segs: Vec<QrSegment> = QrSegment::make_segments(&chrs);
QrCode::encode_segments(&segs, ecl) QrCode::encode_segments(&segs, ecl)
@ -161,9 +161,9 @@ impl QrCode {
/// bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output. /// bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
/// The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version. /// The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
/// ///
/// Returns a wrapped `QrCode` if successful, or `None` if the /// Returns a wrapped `QrCode` if successful, or `Err` if the
/// data is too long to fit in any version at the given ECC level. /// data is too long to fit in any version at the given ECC level.
pub fn encode_binary(data: &[u8], ecl: QrCodeEcc) -> Option<Self> { pub fn encode_binary(data: &[u8], ecl: QrCodeEcc) -> Result<Self,DataTooLong> {
let segs: Vec<QrSegment> = vec![QrSegment::make_bytes(data)]; let segs: Vec<QrSegment> = vec![QrSegment::make_bytes(data)];
QrCode::encode_segments(&segs, ecl) QrCode::encode_segments(&segs, ecl)
} }
@ -180,9 +180,9 @@ impl QrCode {
/// between modes (such as alphanumeric and byte) to encode text in less space. /// between modes (such as alphanumeric and byte) to encode text in less space.
/// This is a mid-level API; the high-level API is `encode_text()` and `encode_binary()`. /// This is a mid-level API; the high-level API is `encode_text()` and `encode_binary()`.
/// ///
/// Returns a wrapped `QrCode` if successful, or `None` if the /// Returns a wrapped `QrCode` if successful, or `Err` if the
/// data is too long to fit in any version at the given ECC level. /// data is too long to fit in any version at the given ECC level.
pub fn encode_segments(segs: &[QrSegment], ecl: QrCodeEcc) -> Option<Self> { pub fn encode_segments(segs: &[QrSegment], ecl: QrCodeEcc) -> Result<Self,DataTooLong> {
QrCode::encode_segments_advanced(segs, ecl, QrCode_MIN_VERSION, QrCode_MAX_VERSION, None, true) QrCode::encode_segments_advanced(segs, ecl, QrCode_MIN_VERSION, QrCode_MAX_VERSION, None, true)
} }
@ -199,10 +199,10 @@ impl QrCode {
/// between modes (such as alphanumeric and byte) to encode text in less space. /// between modes (such as alphanumeric and byte) to encode text in less space.
/// This is a mid-level API; the high-level API is `encode_text()` and `encode_binary()`. /// This is a mid-level API; the high-level API is `encode_text()` and `encode_binary()`.
/// ///
/// Returns a wrapped `QrCode` if successful, or `None` if the data is too /// Returns a wrapped `QrCode` if successful, or `Err` if the data is too
/// long to fit in any version in the given range at the given ECC level. /// long to fit in any version in the given range at the given ECC level.
pub fn encode_segments_advanced(segs: &[QrSegment], mut ecl: QrCodeEcc, pub fn encode_segments_advanced(segs: &[QrSegment], mut ecl: QrCodeEcc,
minversion: Version, maxversion: Version, mask: Option<Mask>, boostecl: bool) -> Option<Self> { minversion: Version, maxversion: Version, mask: Option<Mask>, boostecl: bool) -> Result<Self,DataTooLong> {
assert!(minversion.value() <= maxversion.value(), "Invalid value"); assert!(minversion.value() <= maxversion.value(), "Invalid value");
// Find the minimal version number to use // Find the minimal version number to use
@ -211,14 +211,20 @@ impl QrCode {
loop { loop {
// Number of data bits available // Number of data bits available
let datacapacitybits: usize = QrCode::get_num_data_codewords(version, ecl) * 8; let datacapacitybits: usize = QrCode::get_num_data_codewords(version, ecl) * 8;
if let Some(n) = QrSegment::get_total_bits(segs, version) { let dataused: Option<usize> = QrSegment::get_total_bits(segs, version);
if let Some(n) = dataused {
if n <= datacapacitybits { if n <= datacapacitybits {
datausedbits = n; datausedbits = n;
break; // This version number is found to be suitable break; // This version number is found to be suitable
} }
} }
if version.value() >= maxversion.value() { // All versions in the range could not fit the given data if version.value() >= maxversion.value() { // All versions in the range could not fit the given data
return None; let msg: String = match dataused {
None => String::from("Segment too long"),
Some(n) => format!("Data length = {} bits, Max capacity = {} bits",
n, datacapacitybits),
};
return Err(DataTooLong(msg));
} }
version = Version::new(version.value() + 1); version = Version::new(version.value() + 1);
} }
@ -263,7 +269,7 @@ impl QrCode {
} }
// Create the QR Code object // Create the QR Code object
Some(QrCode::encode_codewords(version, ecl, &datacodewords, mask)) Ok(QrCode::encode_codewords(version, ecl, &datacodewords, mask))
} }

Loading…
Cancel
Save