mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 12:22:34 +00:00
tests built
This commit is contained in:
@@ -1,468 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009 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.pdf417.decoder;
|
||||
|
||||
import com.google.zxing.FormatException;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.pdf417.PDF417RXingResultMetadata;
|
||||
import com.google.zxing.common.DecoderRXingResult;
|
||||
import com.google.zxing.pdf417.encoder.Compaction;
|
||||
import com.google.zxing.pdf417.encoder.PDF417HighLevelEncoderTestAdapter;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Tests {@link DecodedBitStreamParser}.
|
||||
*/
|
||||
public class PDF417DecoderTestCase extends Assert {
|
||||
|
||||
/**
|
||||
* Tests the first sample given in ISO/IEC 15438:2015(E) - Annex H.4
|
||||
*/
|
||||
@Test
|
||||
public void testStandardSample1() throws FormatException {
|
||||
PDF417RXingResultMetadata resultMetadata = new PDF417RXingResultMetadata();
|
||||
int[] sampleCodes = {20, 928, 111, 100, 17, 53, 923, 1, 111, 104, 923, 3, 64, 416, 34, 923, 4, 258, 446, 67,
|
||||
// we should never reach these
|
||||
1000, 1000, 1000};
|
||||
|
||||
DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 2, resultMetadata);
|
||||
|
||||
assertEquals(0, resultMetadata.getSegmentIndex());
|
||||
assertEquals("017053", resultMetadata.getFileId());
|
||||
assertFalse(resultMetadata.isLastSegment());
|
||||
assertEquals(4, resultMetadata.getSegmentCount());
|
||||
assertEquals("CEN BE", resultMetadata.getSender());
|
||||
assertEquals("ISO CH", resultMetadata.getAddressee());
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
int[] optionalData = resultMetadata.getOptionalData();
|
||||
assertEquals("first element of optional array should be the first field identifier", 1, optionalData[0]);
|
||||
assertEquals("last element of optional array should be the last codeword of the last field",
|
||||
67, optionalData[optionalData.length - 1]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests the second given in ISO/IEC 15438:2015(E) - Annex H.4
|
||||
*/
|
||||
@Test
|
||||
public void testStandardSample2() throws FormatException {
|
||||
PDF417RXingResultMetadata resultMetadata = new PDF417RXingResultMetadata();
|
||||
int[] sampleCodes = {11, 928, 111, 103, 17, 53, 923, 1, 111, 104, 922,
|
||||
// we should never reach these
|
||||
1000, 1000, 1000};
|
||||
|
||||
DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 2, resultMetadata);
|
||||
|
||||
assertEquals(3, resultMetadata.getSegmentIndex());
|
||||
assertEquals("017053", resultMetadata.getFileId());
|
||||
assertTrue(resultMetadata.isLastSegment());
|
||||
assertEquals(4, resultMetadata.getSegmentCount());
|
||||
assertNull(resultMetadata.getAddressee());
|
||||
assertNull(resultMetadata.getSender());
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
int[] optionalData = resultMetadata.getOptionalData();
|
||||
assertEquals("first element of optional array should be the first field identifier", 1, optionalData[0]);
|
||||
assertEquals("last element of optional array should be the last codeword of the last field",
|
||||
104, optionalData[optionalData.length - 1]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests the example given in ISO/IEC 15438:2015(E) - Annex H.6
|
||||
*/
|
||||
@Test
|
||||
public void testStandardSample3() throws FormatException {
|
||||
PDF417RXingResultMetadata resultMetadata = new PDF417RXingResultMetadata();
|
||||
int[] sampleCodes = {7, 928, 111, 100, 100, 200, 300,
|
||||
0}; // Final dummy ECC codeword required to avoid ArrayIndexOutOfBounds
|
||||
|
||||
DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 2, resultMetadata);
|
||||
|
||||
assertEquals(0, resultMetadata.getSegmentIndex());
|
||||
assertEquals("100200300", resultMetadata.getFileId());
|
||||
assertFalse(resultMetadata.isLastSegment());
|
||||
assertEquals(-1, resultMetadata.getSegmentCount());
|
||||
assertNull(resultMetadata.getAddressee());
|
||||
assertNull(resultMetadata.getSender());
|
||||
assertNull(resultMetadata.getOptionalData());
|
||||
|
||||
// Check that symbol containing no data except Macro is accepted (see note in Annex H.2)
|
||||
DecoderRXingResult decoderRXingResult = DecodedBitStreamParser.decode(sampleCodes, "0");
|
||||
assertEquals("", decoderRXingResult.getText());
|
||||
assertNotNull(decoderRXingResult.getOther());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSampleWithFilename() throws FormatException {
|
||||
int[] sampleCodes = {23, 477, 928, 111, 100, 0, 252, 21, 86, 923, 0, 815, 251, 133, 12, 148, 537, 593,
|
||||
599, 923, 1, 111, 102, 98, 311, 355, 522, 920, 779, 40, 628, 33, 749, 267, 506, 213, 928, 465, 248,
|
||||
493, 72, 780, 699, 780, 493, 755, 84, 198, 628, 368, 156, 198, 809, 19, 113};
|
||||
PDF417RXingResultMetadata resultMetadata = new PDF417RXingResultMetadata();
|
||||
|
||||
DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 3, resultMetadata);
|
||||
|
||||
assertEquals(0, resultMetadata.getSegmentIndex());
|
||||
assertEquals("000252021086", resultMetadata.getFileId());
|
||||
assertFalse(resultMetadata.isLastSegment());
|
||||
assertEquals(2, resultMetadata.getSegmentCount());
|
||||
assertNull(resultMetadata.getAddressee());
|
||||
assertNull(resultMetadata.getSender());
|
||||
assertEquals("filename.txt", resultMetadata.getFileName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSampleWithNumericValues() throws FormatException {
|
||||
int[] sampleCodes = {25, 477, 928, 111, 100, 0, 252, 21, 86, 923, 2, 2, 0, 1, 0, 0, 0, 923, 5, 130, 923,
|
||||
6, 1, 500, 13, 0};
|
||||
PDF417RXingResultMetadata resultMetadata = new PDF417RXingResultMetadata();
|
||||
|
||||
DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 3, resultMetadata);
|
||||
|
||||
assertEquals(0, resultMetadata.getSegmentIndex());
|
||||
assertEquals("000252021086", resultMetadata.getFileId());
|
||||
assertFalse(resultMetadata.isLastSegment());
|
||||
|
||||
assertEquals(180980729000000L, resultMetadata.getTimestamp());
|
||||
assertEquals(30, resultMetadata.getFileSize());
|
||||
assertEquals(260013, resultMetadata.getChecksum());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSampleWithMacroTerminatorOnly() throws FormatException {
|
||||
int[] sampleCodes = {7, 477, 928, 222, 198, 0, 922};
|
||||
PDF417RXingResultMetadata resultMetadata = new PDF417RXingResultMetadata();
|
||||
|
||||
DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 3, resultMetadata);
|
||||
|
||||
assertEquals(99998, resultMetadata.getSegmentIndex());
|
||||
assertEquals("000", resultMetadata.getFileId());
|
||||
assertTrue(resultMetadata.isLastSegment());
|
||||
assertEquals(-1, resultMetadata.getSegmentCount());
|
||||
assertNull(resultMetadata.getOptionalData());
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testSampleWithBadSequenceIndexMacro() throws FormatException {
|
||||
int[] sampleCodes = {3, 928, 222, 0};
|
||||
PDF417RXingResultMetadata resultMetadata = new PDF417RXingResultMetadata();
|
||||
DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 2, resultMetadata);
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testSampleWithNoFileIdMacro() throws FormatException {
|
||||
int[] sampleCodes = {4, 928, 222, 198, 0};
|
||||
PDF417RXingResultMetadata resultMetadata = new PDF417RXingResultMetadata();
|
||||
DecodedBitStreamParser.decodeMacroBlock(sampleCodes, 2, resultMetadata);
|
||||
}
|
||||
|
||||
@Test(expected = FormatException.class)
|
||||
public void testSampleWithNoDataNoMacro() throws FormatException {
|
||||
int[] sampleCodes = {3, 899, 899, 0};
|
||||
DecodedBitStreamParser.decode(sampleCodes, "0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUppercase() throws WriterException, FormatException {
|
||||
//encodeDecode("", 0);
|
||||
performEncodeTest('A', new int[] { 3, 4, 5, 6, 4, 4, 5, 5});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNumeric() throws WriterException, FormatException {
|
||||
performEncodeTest('1', new int[] { 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testByte() throws WriterException, FormatException {
|
||||
performEncodeTest('\u00c4', new int[] { 3, 4, 5, 6, 7, 7, 8});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUppercaseLowercaseMix1() throws WriterException, FormatException {
|
||||
encodeDecode("aA", 4);
|
||||
encodeDecode("aAa", 5);
|
||||
encodeDecode("Aa", 4);
|
||||
encodeDecode("Aaa", 5);
|
||||
encodeDecode("AaA", 5);
|
||||
encodeDecode("AaaA", 6);
|
||||
encodeDecode("Aaaa", 6);
|
||||
encodeDecode("AaAaA", 5);
|
||||
encodeDecode("AaaAaaA", 6);
|
||||
encodeDecode("AaaAAaaA", 7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPunctuation() throws WriterException, FormatException {
|
||||
performEncodeTest(';', new int[] { 3, 4, 5, 6, 6, 7, 8});
|
||||
encodeDecode(";;;;;;;;;;;;;;;;", 17);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUppercaseLowercaseMix2() throws WriterException, FormatException {
|
||||
performPermutationTest(new char[] {'A', 'a'}, 10, 8972);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUppercaseNumericMix() throws WriterException, FormatException {
|
||||
performPermutationTest(new char[] {'A', '1'}, 14, 192510);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUppercaseMixedMix() throws WriterException, FormatException {
|
||||
performPermutationTest(new char[] {'A', '1', ' ', ';'}, 7, 106060);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUppercasePunctuationMix() throws WriterException, FormatException {
|
||||
performPermutationTest(new char[] {'A', ';'}, 10, 8967);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUppercaseByteMix() throws WriterException, FormatException {
|
||||
performPermutationTest(new char[] {'A', '\u00c4'}, 10, 11222);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLowercaseByteMix() throws WriterException, FormatException {
|
||||
performPermutationTest(new char[] {'a', '\u00c4'}, 10, 11233);
|
||||
}
|
||||
|
||||
public void testUppercaseLowercaseNumericMix() throws WriterException, FormatException {
|
||||
performPermutationTest(new char[] {'A', 'a', '1'}, 7, 15491);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUppercaseLowercasePunctuationMix() throws WriterException, FormatException {
|
||||
performPermutationTest(new char[] {'A', 'a', ';'}, 7, 15491);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUppercaseLowercaseByteMix() throws WriterException, FormatException {
|
||||
performPermutationTest(new char[] {'A', 'a', '\u00c4'}, 7, 17288);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLowercasePunctuationByteMix() throws WriterException, FormatException {
|
||||
performPermutationTest(new char[] {'a', ';', '\u00c4'}, 7, 17427);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUppercaseLowercaseNumericPunctuationMix() throws WriterException, FormatException {
|
||||
performPermutationTest(new char[] {'A', 'a', '1', ';'}, 7, 120479);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBinaryData() throws WriterException, FormatException {
|
||||
byte[] bytes = new byte[500];
|
||||
Random random = new Random(0);
|
||||
int total = 0;
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
random.nextBytes(bytes);
|
||||
total += encodeDecode(new String(bytes, StandardCharsets.ISO_8859_1));
|
||||
}
|
||||
assertEquals(4190044, total);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testECIEnglishHiragana() throws Exception {
|
||||
//multi ECI UTF-8, UTF-16 and ISO-8859-1
|
||||
performECITest(new char[] {'a', '1', '\u3040'}, new float[] {20f, 1f, 10f}, 105825, 110914);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testECIEnglishKatakana() throws Exception {
|
||||
//multi ECI UTF-8, UTF-16 and ISO-8859-1
|
||||
performECITest(new char[] {'a', '1', '\u30a0'}, new float[] {20f, 1f, 10f}, 109177, 110914);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testECIEnglishHalfWidthKatakana() throws Exception {
|
||||
//single ECI
|
||||
performECITest(new char[] {'a', '1', '\uff80'}, new float[] {20f, 1f, 10f}, 80617, 110914);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testECIEnglishChinese() throws Exception {
|
||||
//single ECI
|
||||
performECITest(new char[] {'a', '1', '\u4e00'}, new float[] {20f, 1f, 10f}, 95797, 110914);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testECIGermanCyrillic() throws Exception {
|
||||
//single ECI since the German Umlaut is in ISO-8859-1
|
||||
performECITest(new char[] {'a', '1', '\u00c4', '\u042f'}, new float[] {20f, 1f, 1f, 10f}, 80755, 96007);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testECIEnglishCzechCyrillic1() throws Exception {
|
||||
//multi ECI between ISO-8859-2 and ISO-8859-5
|
||||
performECITest(new char[] {'a', '1', '\u010c', '\u042f'}, new float[] {10f, 1f, 10f, 10f}, 102824, 124525);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testECIEnglishCzechCyrillic2() throws Exception {
|
||||
//multi ECI between ISO-8859-2 and ISO-8859-5
|
||||
performECITest(new char[] {'a', '1', '\u010c', '\u042f'}, new float[] {40f, 1f, 10f, 10f}, 81321, 88236);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testECIEnglishArabicCyrillic() throws Exception {
|
||||
//multi ECI between UTF-8 (ISO-8859-6 is excluded in CharacterSetECI) and ISO-8859-5
|
||||
performECITest(new char[] {'a', '1', '\u0620', '\u042f'}, new float[] {10f, 1f, 10f, 10f}, 118510, 124525);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBinaryMultiECI() throws Exception {
|
||||
//Test the cases described in 5.5.5.3 "ECI and Byte Compaction mode using latch 924 and 901"
|
||||
performDecodeTest(new int[] {5, 927, 4, 913, 200}, "\u010c");
|
||||
performDecodeTest(new int[] {9, 927, 4, 913, 200, 927, 7, 913, 207}, "\u010c\u042f");
|
||||
performDecodeTest(new int[] {9, 927, 4, 901, 200, 927, 7, 901, 207}, "\u010c\u042f");
|
||||
performDecodeTest(new int[] {8, 927, 4, 901, 200, 927, 7, 207}, "\u010c\u042f");
|
||||
performDecodeTest(new int[] {14, 927, 4, 901, 200, 927, 7, 207, 927, 4, 200, 927, 7, 207},
|
||||
"\u010c\u042f\u010c\u042f");
|
||||
performDecodeTest(new int[] {16, 927, 4, 924, 336, 432, 197, 51, 300, 927, 7, 348, 231, 311, 858, 567},
|
||||
"\u010c\u010c\u010c\u010c\u010c\u010c\u042f\u042f\u042f\u042f\u042f\u042f");
|
||||
}
|
||||
|
||||
private static void encodeDecode(String input, int expectedLength) throws WriterException, FormatException {
|
||||
assertEquals(expectedLength, encodeDecode(input));
|
||||
}
|
||||
|
||||
private static int encodeDecode(String input) throws WriterException, FormatException {
|
||||
return encodeDecode(input, null, false, true);
|
||||
}
|
||||
|
||||
private static int encodeDecode(String input, Charset charset, boolean autoECI, boolean decode)
|
||||
throws WriterException, FormatException {
|
||||
String s = PDF417HighLevelEncoderTestAdapter.encodeHighLevel(input, Compaction.AUTO, charset, autoECI);
|
||||
if (decode) {
|
||||
int[] codewords = new int[s.length() + 1];
|
||||
codewords[0] = codewords.length;
|
||||
for (int i = 1; i < codewords.length; i++) {
|
||||
codewords[i] = s.charAt(i - 1);
|
||||
}
|
||||
performDecodeTest(codewords, input);
|
||||
}
|
||||
return s.length() + 1;
|
||||
}
|
||||
|
||||
private static int getEndIndex(int length, char[] chars) {
|
||||
double decimalLength = Math.log10(chars.length);
|
||||
return (int) Math.ceil(Math.pow(10, decimalLength * length));
|
||||
}
|
||||
|
||||
private static String generatePermutation(int index, int length, char[] chars) {
|
||||
int N = chars.length;
|
||||
String baseNNumber = Integer.toString(index, N);
|
||||
while (baseNNumber.length() < length) {
|
||||
baseNNumber = "0" + baseNNumber;
|
||||
}
|
||||
String prefix = "";
|
||||
for (int i = 0; i < baseNNumber.length(); i++) {
|
||||
prefix += chars[baseNNumber.charAt(i) - '0'];
|
||||
}
|
||||
return prefix;
|
||||
}
|
||||
|
||||
private static void performPermutationTest(char[] chars, int length, int expectedTotal) throws WriterException,
|
||||
FormatException {
|
||||
int endIndex = getEndIndex(length, chars);
|
||||
int total = 0;
|
||||
for (int i = 0; i < endIndex; i++) {
|
||||
total += encodeDecode(generatePermutation(i, length, chars));
|
||||
}
|
||||
assertEquals(expectedTotal, total);
|
||||
}
|
||||
|
||||
private static void performEncodeTest(char c, int[] expectedLengths) throws WriterException, FormatException {
|
||||
for (int i = 0; i < expectedLengths.length; i++) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int j = 0; j <= i; j++) {
|
||||
sb.append(c);
|
||||
}
|
||||
encodeDecode(sb.toString(), expectedLengths[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private static void performDecodeTest(int[] codewords, String expectedRXingResult) throws FormatException {
|
||||
DecoderRXingResult result = DecodedBitStreamParser.decode(codewords, "0");
|
||||
assertEquals(expectedRXingResult, result.getText());
|
||||
}
|
||||
|
||||
private static void performECITest(char[] chars,
|
||||
float[] weights,
|
||||
int expectedMinLength,
|
||||
int expectedUTFLength) throws WriterException, FormatException {
|
||||
Random random = new Random(0);
|
||||
int minLength = 0;
|
||||
int utfLength = 0;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
String s = generateText(random, 100, chars, weights);
|
||||
minLength += encodeDecode(s, null, true, true);
|
||||
utfLength += encodeDecode(s, StandardCharsets.UTF_8, false, true);
|
||||
}
|
||||
assertEquals(expectedMinLength, minLength);
|
||||
assertEquals(expectedUTFLength, utfLength);
|
||||
}
|
||||
|
||||
private static String generateText(Random random, int maxWidth, char[] chars, float[] weights) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
final int maxWordWidth = 7;
|
||||
float total = 0;
|
||||
for (int i = 0; i < weights.length; i++) {
|
||||
total += weights[i];
|
||||
}
|
||||
for (int i = 0; i < weights.length; i++) {
|
||||
weights[i] /= total;
|
||||
}
|
||||
int cnt = 0;
|
||||
do {
|
||||
float maxValue = 0;
|
||||
int maxIndex = 0;
|
||||
for (int j = 0; j < weights.length; j++) {
|
||||
float value = random.nextFloat() * weights[j];
|
||||
if (value > maxValue) {
|
||||
maxValue = value;
|
||||
maxIndex = j;
|
||||
}
|
||||
}
|
||||
final float wordLength = maxWordWidth * random.nextFloat();
|
||||
if (wordLength > 0 && result.length() > 0) {
|
||||
result.append(' ');
|
||||
}
|
||||
for (int j = 0; j < wordLength; j++) {
|
||||
char c = chars[maxIndex];
|
||||
if (j == 0 && c >= 'a' && c <= 'z' && random.nextBoolean()) {
|
||||
c = (char) (c - 'a' + 'A');
|
||||
}
|
||||
result.append(c);
|
||||
}
|
||||
if (cnt % 2 != 0 && random.nextBoolean()) {
|
||||
result.append('.');
|
||||
}
|
||||
cnt++;
|
||||
} while (result.length() < maxWidth - maxWordWidth);
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
@@ -189,7 +189,7 @@ pub fn decode(codewords: &[u32], ecLevel: &str) -> Result<DecoderRXingResult, Ex
|
||||
Vec::new(),
|
||||
ecLevel.to_owned(),
|
||||
);
|
||||
decoderRXingResult.setOther(Rc::new(resultMetadata));
|
||||
decoderRXingResult.setOther(Some(Rc::new(resultMetadata)));
|
||||
|
||||
Ok(decoderRXingResult)
|
||||
}
|
||||
|
||||
@@ -25,3 +25,6 @@ pub use detection_result::*;
|
||||
|
||||
pub mod decoded_bit_stream_parser;
|
||||
pub mod pdf_417_scanning_decoder;
|
||||
|
||||
#[cfg(test)]
|
||||
mod pdf_417_decoder_test_case;
|
||||
|
||||
517
src/pdf417/decoder/pdf_417_decoder_test_case.rs
Normal file
517
src/pdf417/decoder/pdf_417_decoder_test_case.rs
Normal file
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
* Copyright 2009 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.
|
||||
*/
|
||||
|
||||
use encoding::{EncodingRef, Encoding};
|
||||
use rand::{self, Rng};
|
||||
use rand::rngs::ThreadRng;
|
||||
|
||||
use crate::pdf417::PDF417RXingResultMetadata;
|
||||
use crate::pdf417::decoder::decoded_bit_stream_parser;
|
||||
use crate::pdf417::encoder::{pdf_417_high_level_encoder_test_adapter, Compaction};
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link DecodedBitStreamParser}.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Tests the first sample given in ISO/IEC 15438:2015(E) - Annex H.4
|
||||
*/
|
||||
#[test]
|
||||
fn testStandardSample1() {
|
||||
let mut resultMetadata = PDF417RXingResultMetadata::default();
|
||||
let sampleCodes:[u32;23] = [20, 928, 111, 100, 17, 53, 923, 1, 111, 104, 923, 3, 64, 416, 34, 923, 4, 258, 446, 67,
|
||||
// we should never reach these
|
||||
1000, 1000, 1000];
|
||||
|
||||
decoded_bit_stream_parser::decodeMacroBlock(&sampleCodes, 2,&mut resultMetadata);
|
||||
|
||||
assert_eq!(0, resultMetadata.getSegmentIndex());
|
||||
assert_eq!("017053", resultMetadata.getFileId());
|
||||
assert!(!resultMetadata.isLastSegment());
|
||||
assert_eq!(4, resultMetadata.getSegmentCount());
|
||||
assert_eq!("CEN BE", resultMetadata.getSender());
|
||||
assert_eq!("ISO CH", resultMetadata.getAddressee());
|
||||
|
||||
let optionalData = resultMetadata.getOptionalData();
|
||||
assert_eq!( 1, optionalData[0],"first element of optional array should be the first field identifier");
|
||||
assert_eq!(
|
||||
67, optionalData[optionalData.len() - 1],"last element of optional array should be the last codeword of the last field");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests the second given in ISO/IEC 15438:2015(E) - Annex H.4
|
||||
*/
|
||||
#[test]
|
||||
fn testStandardSample2() {
|
||||
let mut resultMetadata = PDF417RXingResultMetadata::default();
|
||||
let sampleCodes :[u32;14]= [11, 928, 111, 103, 17, 53, 923, 1, 111, 104, 922,
|
||||
// we should never reach these
|
||||
1000, 1000, 1000];
|
||||
|
||||
decoded_bit_stream_parser::decodeMacroBlock(&sampleCodes, 2, &mut resultMetadata);
|
||||
|
||||
assert_eq!(3, resultMetadata.getSegmentIndex());
|
||||
assert_eq!("017053", resultMetadata.getFileId());
|
||||
assert!(resultMetadata.isLastSegment());
|
||||
assert_eq!(4, resultMetadata.getSegmentCount());
|
||||
assert!(resultMetadata.getAddressee().is_empty());
|
||||
assert!(resultMetadata.getSender().is_empty());
|
||||
|
||||
|
||||
let optionalData = resultMetadata.getOptionalData();
|
||||
assert_eq!( 1, optionalData[0],"first element of optional array should be the first field identifier");
|
||||
assert_eq!(
|
||||
104, optionalData[optionalData.len() - 1],"last element of optional array should be the last codeword of the last field");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests the example given in ISO/IEC 15438:2015(E) - Annex H.6
|
||||
*/
|
||||
#[test]
|
||||
fn testStandardSample3() {
|
||||
let mut resultMetadata = PDF417RXingResultMetadata::default();
|
||||
let sampleCodes = [7_u32, 928, 111, 100, 100, 200, 300,
|
||||
0]; // Final dummy ECC codeword required to avoid ArrayIndexOutOfBounds
|
||||
|
||||
decoded_bit_stream_parser::decodeMacroBlock(&sampleCodes, 2, &mut resultMetadata);
|
||||
|
||||
assert_eq!(0, resultMetadata.getSegmentIndex());
|
||||
assert_eq!("100200300", resultMetadata.getFileId());
|
||||
assert!(!resultMetadata.isLastSegment());
|
||||
assert_eq!(-1, resultMetadata.getSegmentCount());
|
||||
assert!(resultMetadata.getAddressee().is_empty());
|
||||
assert!(resultMetadata.getSender().is_empty());
|
||||
assert!(resultMetadata.getOptionalData().is_empty());
|
||||
|
||||
// Check that symbol containing no data except Macro is accepted (see note in Annex H.2)
|
||||
let decoderRXingResult = decoded_bit_stream_parser::decode(&sampleCodes, "0").expect("decode");
|
||||
assert_eq!("", decoderRXingResult.getText());
|
||||
assert!(!decoderRXingResult.getOther().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testSampleWithFilename() {
|
||||
let sampleCodes = [23_u32, 477, 928, 111, 100, 0, 252, 21, 86, 923, 0, 815, 251, 133, 12, 148, 537, 593,
|
||||
599, 923, 1, 111, 102, 98, 311, 355, 522, 920, 779, 40, 628, 33, 749, 267, 506, 213, 928, 465, 248,
|
||||
493, 72, 780, 699, 780, 493, 755, 84, 198, 628, 368, 156, 198, 809, 19, 113];
|
||||
let mut resultMetadata = PDF417RXingResultMetadata::default();
|
||||
|
||||
decoded_bit_stream_parser::decodeMacroBlock(&sampleCodes, 3, &mut resultMetadata).expect("decode");
|
||||
|
||||
assert_eq!(0, resultMetadata.getSegmentIndex());
|
||||
assert_eq!("000252021086", resultMetadata.getFileId());
|
||||
assert!(!resultMetadata.isLastSegment());
|
||||
assert_eq!(2, resultMetadata.getSegmentCount());
|
||||
assert!(resultMetadata.getAddressee().is_empty());
|
||||
assert!(resultMetadata.getSender().is_empty());
|
||||
assert_eq!("filename.txt", resultMetadata.getFileName());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testSampleWithNumericValues() {
|
||||
let sampleCodes = [25_u32, 477, 928, 111, 100, 0, 252, 21, 86, 923, 2, 2, 0, 1, 0, 0, 0, 923, 5, 130, 923,
|
||||
6, 1, 500, 13, 0];
|
||||
let mut resultMetadata = PDF417RXingResultMetadata::default();
|
||||
|
||||
decoded_bit_stream_parser::decodeMacroBlock(&sampleCodes, 3, &mut resultMetadata).expect("decode");
|
||||
|
||||
assert_eq!(0, resultMetadata.getSegmentIndex());
|
||||
assert_eq!("000252021086", resultMetadata.getFileId());
|
||||
assert!( !resultMetadata.isLastSegment() );
|
||||
|
||||
assert_eq!(180980729000000, resultMetadata.getTimestamp());
|
||||
assert_eq!(30, resultMetadata.getFileSize());
|
||||
assert_eq!(260013, resultMetadata.getChecksum());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testSampleWithMacroTerminatorOnly() {
|
||||
let sampleCodes = [7_u32, 477, 928, 222, 198, 0, 922];
|
||||
let mut resultMetadata = PDF417RXingResultMetadata::default();
|
||||
|
||||
decoded_bit_stream_parser::decodeMacroBlock(&sampleCodes, 3, &mut resultMetadata).expect("decode");
|
||||
|
||||
assert_eq!(99998, resultMetadata.getSegmentIndex());
|
||||
assert_eq!("000", resultMetadata.getFileId());
|
||||
assert!(resultMetadata.isLastSegment());
|
||||
assert_eq!(-1, resultMetadata.getSegmentCount());
|
||||
assert!(resultMetadata.getOptionalData().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn testSampleWithBadSequenceIndexMacro() {
|
||||
let sampleCodes = [3_u32, 928, 222, 0];
|
||||
let mut resultMetadata = PDF417RXingResultMetadata::default();
|
||||
decoded_bit_stream_parser::decodeMacroBlock(&sampleCodes, 2, &mut resultMetadata).expect("decode");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn testSampleWithNoFileIdMacro() {
|
||||
let sampleCodes = [4_u32, 928, 222, 198, 0];
|
||||
let mut resultMetadata = PDF417RXingResultMetadata::default();
|
||||
decoded_bit_stream_parser::decodeMacroBlock(&sampleCodes, 2, &mut resultMetadata).expect("decode");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn testSampleWithNoDataNoMacro() {
|
||||
let sampleCodes = [3_u32, 899, 899, 0];
|
||||
decoded_bit_stream_parser::decode(&sampleCodes, "0").expect("decode");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testUppercase() {
|
||||
//encodeDecode("", 0);
|
||||
performEncodeTest('A', &[ 3, 4, 5, 6, 4, 4, 5, 5]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testNumeric() {
|
||||
performEncodeTest('1', &[ 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testByte(){
|
||||
performEncodeTest('\u{00c4}', &[ 3, 4, 5, 6, 7, 7, 8]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testUppercaseLowercaseMix1(){
|
||||
encodeDecodeWithLength("aA", 4);
|
||||
encodeDecodeWithLength("aAa", 5);
|
||||
encodeDecodeWithLength("Aa", 4);
|
||||
encodeDecodeWithLength("Aaa", 5);
|
||||
encodeDecodeWithLength("AaA", 5);
|
||||
encodeDecodeWithLength("AaaA", 6);
|
||||
encodeDecodeWithLength("Aaaa", 6);
|
||||
encodeDecodeWithLength("AaAaA", 5);
|
||||
encodeDecodeWithLength("AaaAaaA", 6);
|
||||
encodeDecodeWithLength("AaaAAaaA", 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testPunctuation(){
|
||||
performEncodeTest(';', &[ 3, 4, 5, 6, 6, 7, 8]);
|
||||
encodeDecodeWithLength(";;;;;;;;;;;;;;;;", 17);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testUppercaseLowercaseMix2(){
|
||||
performPermutationTest(&['A', 'a'], 10, 8972);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testUppercaseNumericMix() {
|
||||
performPermutationTest(&['A', '1'], 14, 192510);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testUppercaseMixedMix() {
|
||||
performPermutationTest(&['A', '1', ' ', ';'], 7, 106060);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testUppercasePunctuationMix(){
|
||||
performPermutationTest(&['A', ';'], 10, 8967);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testUppercaseByteMix() {
|
||||
performPermutationTest(&['A', '\u{00c4}'], 10, 11222);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testLowercaseByteMix(){
|
||||
performPermutationTest(&['a', '\u{00c4}'], 10, 11233);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testUppercaseLowercaseNumericMix(){
|
||||
performPermutationTest(&['A', 'a', '1'], 7, 15491);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testUppercaseLowercasePunctuationMix() {
|
||||
performPermutationTest(&['A', 'a', ';'], 7, 15491);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testUppercaseLowercaseByteMix() {
|
||||
performPermutationTest(&['A', 'a', '\u{00c4}'], 7, 17288);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testLowercasePunctuationByteMix(){
|
||||
performPermutationTest(&['a', ';', '\u{00c4}'], 7, 17427);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testUppercaseLowercaseNumericPunctuationMix(){
|
||||
performPermutationTest(&['A', 'a', '1', ';'], 7, 120479);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testBinaryData() {
|
||||
// let bytes = [0_u8;500];
|
||||
// let random = rand::thread_rng();
|
||||
let mut total = 0;
|
||||
for i in 0..10000 {
|
||||
// for (int i = 0; i < 10000; i++) {
|
||||
let bytes = gen_500_random_bytes();
|
||||
|
||||
total += encodeDecode(&encoding::all::ISO_8859_1.decode(&bytes, encoding::DecoderTrap::Strict).expect("decode bytes"));
|
||||
}
|
||||
assert_eq!(4190044, total);
|
||||
}
|
||||
|
||||
fn gen_500_random_bytes() -> [u8;500] {
|
||||
let mut bytes = [0_u8;500];
|
||||
let mut random = rand::thread_rng();
|
||||
for i in 0..500 {
|
||||
bytes[i] = random.gen();
|
||||
}
|
||||
bytes
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testECIEnglishHiragana(){
|
||||
//multi ECI UTF-8, UTF-16 and ISO-8859-1
|
||||
performECITest(&['a', '1', '\u{3040}'], &mut [20.0, 1.0, 10.0], 105825, 110914);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testECIEnglishKatakana() {
|
||||
//multi ECI UTF-8, UTF-16 and ISO-8859-1
|
||||
performECITest(&['a', '1', '\u{30a0}'], &mut [20.0, 1.0, 10.0], 109177, 110914);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testECIEnglishHalfWidthKatakana(){
|
||||
//single ECI
|
||||
performECITest(&['a', '1', '\u{ff80}'], &mut [20.0, 1.0, 10.0], 80617, 110914);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testECIEnglishChinese() {
|
||||
//single ECI
|
||||
performECITest(&['a', '1', '\u{4e00}'], &mut [20.0, 1.0, 10.0], 95797, 110914);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testECIGermanCyrillic(){
|
||||
//single ECI since the German Umlaut is in ISO-8859-1
|
||||
performECITest(&['a', '1', '\u{00c4}', '\u{042f}'], &mut [20.0, 1.0, 1.0, 10.0], 80755, 96007);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testECIEnglishCzechCyrillic1() {
|
||||
//multi ECI between ISO-8859-2 and ISO-8859-5
|
||||
performECITest(&['a', '1', '\u{010c}', '\u{042f}'], &mut [10.0, 1.0, 10.0, 10.0], 102824, 124525);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testECIEnglishCzechCyrillic2() {
|
||||
//multi ECI between ISO-8859-2 and ISO-8859-5
|
||||
performECITest(&['a', '1', '\u{010c}', '\u{042f}'], &mut [40.0, 1.0, 10.0, 10.0], 81321, 88236);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testECIEnglishArabicCyrillic() {
|
||||
//multi ECI between UTF-8 (ISO-8859-6 is excluded in CharacterSetECI) and ISO-8859-5
|
||||
performECITest(&['a', '1', '\u{0620}', '\u{042f}'], &mut [10.0, 1.0, 10.0, 10.0], 118510, 124525);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testBinaryMultiECI() {
|
||||
//Test the cases described in 5.5.5.3 "ECI and Byte Compaction mode using latch 924 and 901"
|
||||
performDecodeTest(&[5, 927, 4, 913, 200], "\u{010c}");
|
||||
performDecodeTest(&[9, 927, 4, 913, 200, 927, 7, 913, 207], "\u{010c}\u{042f}");
|
||||
performDecodeTest(&[9, 927, 4, 901, 200, 927, 7, 901, 207], "\u{010c}\u{042f}");
|
||||
performDecodeTest(&[8, 927, 4, 901, 200, 927, 7, 207], "\u{010c}\u{042f}");
|
||||
performDecodeTest(&[14, 927, 4, 901, 200, 927, 7, 207, 927, 4, 200, 927, 7, 207],
|
||||
"\u{010c}\u{042f}\u{010c}\u{042f}");
|
||||
performDecodeTest(&[16, 927, 4, 924, 336, 432, 197, 51, 300, 927, 7, 348, 231, 311, 858, 567],
|
||||
"\u{010c}\u{010c}\u{010c}\u{010c}\u{010c}\u{010c}\u{042f}\u{042f}\u{042f}\u{042f}\u{042f}\u{042f}");
|
||||
}
|
||||
|
||||
fn encodeDecodeWithLength( input:&str, expectedLength:u32) {
|
||||
assert_eq!(expectedLength, encodeDecode(input));
|
||||
}
|
||||
|
||||
fn encodeDecode( input:&str) -> u32 {
|
||||
return encodeDecodeWithAll(input, None, false, true);
|
||||
}
|
||||
|
||||
fn encodeDecodeWithAll( input:&str, charset:Option<EncodingRef>, autoECI:bool, decode:bool)
|
||||
-> u32 {
|
||||
let s = pdf_417_high_level_encoder_test_adapter::encodeHighLevel(input, Compaction::AUTO, charset, autoECI).expect("encode");
|
||||
if decode {
|
||||
let mut codewords = vec![0_u32;s.chars().count() + 1];
|
||||
codewords[0] = codewords.len() as u32;
|
||||
for i in 1..codewords.len() {
|
||||
// for (int i = 1; i < codewords.length; i++) {
|
||||
codewords[i] = s.chars().nth(i - 1).unwrap() as u32;
|
||||
}
|
||||
performDecodeTest(&codewords, input);
|
||||
}
|
||||
s.chars().count() as u32 + 1
|
||||
}
|
||||
|
||||
fn getEndIndex( length:u32, chars:&[char]) -> u32{
|
||||
let decimalLength : f64 = (chars.len() as f64).log10(); //Math.log10(chars.length);
|
||||
(decimalLength*length as f64).powi(10).ceil() as u32
|
||||
// Math.ceil(Math.pow(10, decimalLength * length))
|
||||
}
|
||||
|
||||
fn generatePermutation( index:u32, length:u32, chars:&[char]) -> String{
|
||||
let N = chars.len() as u32;
|
||||
// let baseNNumber = Integer.toString(index, N);
|
||||
let mut baseNNumber= int_to_string(index,N);
|
||||
while baseNNumber.chars().count() < length as usize {
|
||||
baseNNumber.insert(0, '0');
|
||||
// baseNNumber = "0" + baseNNumber;
|
||||
}
|
||||
let mut prefix = String::from("");
|
||||
for ch in baseNNumber.chars() {
|
||||
prefix.push(chars[ch as usize - '0' as usize]);
|
||||
}
|
||||
// for i in 0..baseNNumber.chars().count() {
|
||||
// // for (int i = 0; i < baseNNumber.length(); i++) {
|
||||
// prefix += chars[baseNNumber.charAt(i) - '0'];
|
||||
// }
|
||||
|
||||
|
||||
prefix
|
||||
}
|
||||
|
||||
fn performPermutationTest( chars:&[char], length:u32, expectedTotal:u32) {
|
||||
let endIndex = getEndIndex(length, chars);
|
||||
let mut total = 0;
|
||||
for i in 0..endIndex {
|
||||
// for (int i = 0; i < endIndex; i++) {
|
||||
total += encodeDecode(&generatePermutation(i, length, chars));
|
||||
}
|
||||
assert_eq!(expectedTotal, total);
|
||||
}
|
||||
|
||||
fn performEncodeTest( c:char, expectedLengths:&[u32]) {
|
||||
for i in 0..expectedLengths.len() {
|
||||
// for (int i = 0; i < expectedLengths.length; i++) {
|
||||
let mut sb = String::new();//new StringBuilder();
|
||||
for j in 0..=i {
|
||||
// for (int j = 0; j <= i; j++) {
|
||||
sb.push(c);
|
||||
}
|
||||
encodeDecodeWithLength(&sb, expectedLengths[i]);
|
||||
}
|
||||
}
|
||||
|
||||
fn performDecodeTest(codewords:&[u32], expectedRXingResult:&str) {
|
||||
let result = decoded_bit_stream_parser::decode(codewords, "0").expect("decode");
|
||||
assert_eq!(expectedRXingResult, result.getText());
|
||||
}
|
||||
|
||||
fn performECITest( chars:&[char],
|
||||
weights:&mut [f32],
|
||||
expectedMinLength:u32,
|
||||
expectedUTFLength:u32) {
|
||||
let mut random = rand::thread_rng();
|
||||
let mut minLength = 0;
|
||||
let mut utfLength = 0;
|
||||
for i in 0..1000 {
|
||||
// for (int i = 0; i < 1000; i++) {
|
||||
let s = generateText(&mut random, 100, chars, weights);
|
||||
minLength += encodeDecodeWithAll(&s, None, true, true);
|
||||
utfLength += encodeDecodeWithAll(&s, Some(encoding::all::UTF_8), false, true);
|
||||
}
|
||||
assert_eq!(expectedMinLength, minLength);
|
||||
assert_eq!(expectedUTFLength, utfLength);
|
||||
}
|
||||
|
||||
fn generateText( random:&mut ThreadRng, maxWidth:u32, chars:&[char], weights:&mut [f32]) -> String{
|
||||
let mut result = String::new();//new StringBuilder();
|
||||
let maxWordWidth = 7;
|
||||
let mut total = 0.0;
|
||||
// for (int i = 0; i < weights.length; i++) {
|
||||
// total += weights[i];
|
||||
// }
|
||||
total += weights.iter().sum::<f32>();
|
||||
|
||||
for i in 0..weights.len() {
|
||||
// for (int i = 0; i < weights.length; i++) {
|
||||
weights[i] /= total;
|
||||
}
|
||||
let mut cnt = 0;
|
||||
loop {
|
||||
let mut maxValue = 0.0;
|
||||
let mut maxIndex = 0;
|
||||
for j in 0..weights.len() {
|
||||
// for (int j = 0; j < weights.length; j++) {
|
||||
let value = random.gen::<f32>() * weights[j];
|
||||
if value > maxValue {
|
||||
maxValue = value;
|
||||
maxIndex = j;
|
||||
}
|
||||
}
|
||||
let wordLength = (maxWordWidth as f32 * random.gen::<f32>()) as i32;
|
||||
if wordLength > 0 && result.chars().count() > 0 {
|
||||
result.push(' ');
|
||||
}
|
||||
for j in 0..wordLength {
|
||||
// for (int j = 0; j < wordLength; j++) {
|
||||
let mut c = chars[maxIndex];
|
||||
if j == 0 && c >= 'a' && c <= 'z' && random.gen::<bool>() {
|
||||
c = char::from_u32(c as u32- 'a' as u32 + 'A' as u32).unwrap();
|
||||
}
|
||||
result.push(c);
|
||||
}
|
||||
if cnt % 2 != 0 && random.gen_bool(0.51) {
|
||||
result.push('.');
|
||||
}
|
||||
cnt+=1;
|
||||
|
||||
if !(result.chars().count() < (maxWidth as isize - maxWordWidth as isize) as usize) { break }
|
||||
} //while (result.length() < maxWidth - maxWordWidth);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
|
||||
fn int_to_string(x: u32, radix: u32) -> String {
|
||||
let mut x = x;
|
||||
// Handle the special case of 0
|
||||
if x == 0 {
|
||||
return "0".to_string();
|
||||
}
|
||||
|
||||
// Build the string by repeatedly dividing the number by the radix and
|
||||
// adding the remainder to the beginning of the string
|
||||
let mut s = String::new();
|
||||
while x > 0 {
|
||||
let remainder = (x % radix) as u8;
|
||||
s = (remainder as char).to_string() + &s;
|
||||
x /= radix;
|
||||
}
|
||||
|
||||
s
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user