mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
TelResultParser port with pass
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
// package com.google.zxing.client.result;
|
||||
|
||||
use std::any::Any;
|
||||
|
||||
use super::ParsedRXingResultType;
|
||||
|
||||
/**
|
||||
@@ -30,34 +32,33 @@ use super::ParsedRXingResultType;
|
||||
* @author Sean Owen
|
||||
*/
|
||||
pub trait ParsedRXingResult {
|
||||
// private final ParsedRXingResultType type;
|
||||
|
||||
// private final ParsedRXingResultType type;
|
||||
// protected ParsedRXingResult(ParsedRXingResultType type) {
|
||||
// this.type = type;
|
||||
// }
|
||||
|
||||
// protected ParsedRXingResult(ParsedRXingResultType type) {
|
||||
// this.type = type;
|
||||
// }
|
||||
fn getType(&self) -> ParsedRXingResultType;
|
||||
// fn as_any(&self) -> &dyn Any;
|
||||
|
||||
fn getType(&self) -> ParsedRXingResultType;
|
||||
fn getDisplayRXingResult(&self) -> String;
|
||||
|
||||
fn getDisplayRXingResult(&self) -> String;
|
||||
|
||||
fn maybe_append(&self, value :&str, result:&mut String) {
|
||||
if !value.is_empty() {
|
||||
// Don't add a newline before the first value
|
||||
if result.len() > 0 {
|
||||
result.push('\n');
|
||||
}
|
||||
result.push_str(value);
|
||||
fn maybe_append(&self, value: &str, result: &mut String) {
|
||||
if !value.is_empty() {
|
||||
// Don't add a newline before the first value
|
||||
if result.len() > 0 {
|
||||
result.push('\n');
|
||||
}
|
||||
result.push_str(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_append_multiple(&self, values:&[&str], result:&mut String) {
|
||||
if !values.is_empty() {
|
||||
for value in values {
|
||||
// for (String value : values) {
|
||||
self.maybe_append(value, result);
|
||||
}
|
||||
fn maybe_append_multiple(&self, values: &[&str], result: &mut String) {
|
||||
if !values.is_empty() {
|
||||
for value in values {
|
||||
// for (String value : values) {
|
||||
self.maybe_append(value, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
#[derive(Debug,PartialEq, Eq,Hash)]
|
||||
pub enum ParsedRXingResultType {
|
||||
|
||||
ADDRESSBOOK,
|
||||
|
||||
@@ -33,7 +33,7 @@ use urlencoding::decode;
|
||||
|
||||
use crate::{exceptions::Exceptions, RXingResult};
|
||||
|
||||
use super::ParsedRXingResult;
|
||||
use super::{ParsedClientResult, ParsedRXingResult, TextParsedRXingResult, TelRXingResultParser};
|
||||
|
||||
/**
|
||||
* <p>Abstract class representing the result of decoding a barcode, as more than
|
||||
@@ -47,7 +47,58 @@ use super::ParsedRXingResult;
|
||||
* @author Sean Owen
|
||||
*/
|
||||
pub trait RXingResultParser {
|
||||
// private static final RXingResultParser[] PARSERS = {
|
||||
|
||||
// const PARSERS: [&'static str; 20] = [
|
||||
// "BookmarkDoCoMoRXingResultParser",
|
||||
// "AddressBookDoCoMoRXingResultParser",
|
||||
// "EmailDoCoMoRXingResultParser",
|
||||
// "AddressBookAURXingResultParser",
|
||||
// "VCardRXingResultParser",
|
||||
// "BizcardRXingResultParser",
|
||||
// "VEventRXingResultParser",
|
||||
// "EmailAddressRXingResultParser",
|
||||
// "SMTPRXingResultParser",
|
||||
// "TelRXingResultParser",
|
||||
// "SMSMMSRXingResultParser",
|
||||
// "SMSTOMMSTORXingResultParser",
|
||||
// "GeoRXingResultParser",
|
||||
// "WifiRXingResultParser",
|
||||
// "URLTORXingResultParser",
|
||||
// "URIRXingResultParser",
|
||||
// "ISBNRXingResultParser",
|
||||
// "ProductRXingResultParser",
|
||||
// "ExpandedProductRXingResultParser",
|
||||
// "VINRXingResultParser",
|
||||
// ];
|
||||
|
||||
/**
|
||||
* Attempts to parse the raw {@link RXingResult}'s contents as a particular type
|
||||
* of information (email, URL, etc.) and return a {@link ParsedRXingResult} encapsulating
|
||||
* the result of parsing.
|
||||
*
|
||||
* @param theRXingResult the raw {@link RXingResult} to parse
|
||||
* @return {@link ParsedRXingResult} encapsulating the parsing result
|
||||
*/
|
||||
fn parse(&self, theRXingResult: &RXingResult) -> Option<ParsedClientResult>;
|
||||
}
|
||||
|
||||
const DIGITS: &'static str = "\\d+"; //= Pattern.compile("\\d+");
|
||||
const AMPERSAND: &'static str = "&"; // private static final Pattern AMPERSAND = Pattern.compile("&");
|
||||
const EQUALS: &'static str = "="; //private static final Pattern EQUALS = Pattern.compile("=");
|
||||
const BYTE_ORDER_MARK: &'static str = "\u{feff}"; //private static final String BYTE_ORDER_MARK = "\ufeff";
|
||||
|
||||
const EMPTY_STR_ARRAY: &'static str = "";
|
||||
|
||||
pub fn getMassagedText(result: &RXingResult) -> String {
|
||||
let mut text = result.getText().clone();
|
||||
if text.starts_with(BYTE_ORDER_MARK) {
|
||||
text = text[1..].to_owned();
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
pub fn parseRXingResult(theRXingResult: &RXingResult) -> ParsedClientResult {
|
||||
let PARSERS = [
|
||||
// new BookmarkDoCoMoRXingResultParser(),
|
||||
// new AddressBookDoCoMoRXingResultParser(),
|
||||
// new EmailDoCoMoRXingResultParser(),
|
||||
@@ -57,7 +108,7 @@ pub trait RXingResultParser {
|
||||
// new VEventRXingResultParser(),
|
||||
// new EmailAddressRXingResultParser(),
|
||||
// new SMTPRXingResultParser(),
|
||||
// new TelRXingResultParser(),
|
||||
TelRXingResultParser{},
|
||||
// new SMSMMSRXingResultParser(),
|
||||
// new SMSTOMMSTORXingResultParser(),
|
||||
// new GeoRXingResultParser(),
|
||||
@@ -68,278 +119,233 @@ pub trait RXingResultParser {
|
||||
// new ProductRXingResultParser(),
|
||||
// new ExpandedProductRXingResultParser(),
|
||||
// new VINRXingResultParser(),
|
||||
// };
|
||||
];
|
||||
|
||||
const DIGITS: &'static str = "\\d+"; //= Pattern.compile("\\d+");
|
||||
const AMPERSAND: &'static str = "&"; // private static final Pattern AMPERSAND = Pattern.compile("&");
|
||||
const EQUALS: &'static str = "="; //private static final Pattern EQUALS = Pattern.compile("=");
|
||||
const BYTE_ORDER_MARK: &'static str = "\u{feff}"; //private static final String BYTE_ORDER_MARK = "\ufeff";
|
||||
|
||||
const EMPTY_STR_ARRAY: &'static str = "";
|
||||
|
||||
const PARSERS: [&'static str; 20] = [
|
||||
"BookmarkDoCoMoRXingResultParser",
|
||||
"AddressBookDoCoMoRXingResultParser",
|
||||
"EmailDoCoMoRXingResultParser",
|
||||
"AddressBookAURXingResultParser",
|
||||
"VCardRXingResultParser",
|
||||
"BizcardRXingResultParser",
|
||||
"VEventRXingResultParser",
|
||||
"EmailAddressRXingResultParser",
|
||||
"SMTPRXingResultParser",
|
||||
"TelRXingResultParser",
|
||||
"SMSMMSRXingResultParser",
|
||||
"SMSTOMMSTORXingResultParser",
|
||||
"GeoRXingResultParser",
|
||||
"WifiRXingResultParser",
|
||||
"URLTORXingResultParser",
|
||||
"URIRXingResultParser",
|
||||
"ISBNRXingResultParser",
|
||||
"ProductRXingResultParser",
|
||||
"ExpandedProductRXingResultParser",
|
||||
"VINRXingResultParser",
|
||||
];
|
||||
|
||||
/**
|
||||
* Attempts to parse the raw {@link RXingResult}'s contents as a particular type
|
||||
* of information (email, URL, etc.) and return a {@link ParsedRXingResult} encapsulating
|
||||
* the result of parsing.
|
||||
*
|
||||
* @param theRXingResult the raw {@link RXingResult} to parse
|
||||
* @return {@link ParsedRXingResult} encapsulating the parsing result
|
||||
*/
|
||||
fn parse(&self, theRXingResult: &RXingResult) -> Self;
|
||||
|
||||
fn getMassagedText(result: &RXingResult) -> String {
|
||||
let mut text = result.getText().clone();
|
||||
if text.starts_with(Self::BYTE_ORDER_MARK) {
|
||||
text = text[1..].to_owned();
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
fn parseRXingResult(theRXingResult: &RXingResult) -> Box<dyn ParsedRXingResult> {
|
||||
for parser in Self::PARSERS {
|
||||
// for (RXingResultParser parser : PARSERS) {
|
||||
todo!("implement multiple parsers");
|
||||
}
|
||||
// ParsedRXingResult result = parser.parse(theRXingResult);
|
||||
// if (result != null) {
|
||||
// return result;
|
||||
// }
|
||||
// }
|
||||
// return new TextParsedRXingResult(theRXingResult.getText(), null);
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn maybe_ppend_string(value: &str, result: &mut String) {
|
||||
if !value.is_empty() {
|
||||
result.push('\n');
|
||||
result.push_str(value);
|
||||
for parser in PARSERS {
|
||||
let result = parser.parse(theRXingResult);
|
||||
if result.is_some() {
|
||||
return result.unwrap();
|
||||
}
|
||||
}
|
||||
// ParsedRXingResult result = parser.parse(theRXingResult);
|
||||
// if (result != null) {
|
||||
// return result;
|
||||
// }
|
||||
// }
|
||||
|
||||
fn maybe_append_multiple(value: &[&str], result: &mut String) {
|
||||
if !value.is_empty() {
|
||||
for s in value {
|
||||
// for (String s : value) {
|
||||
result.push('\n');
|
||||
result.push_str(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
ParsedClientResult::TextResult(TextParsedRXingResult::new(
|
||||
theRXingResult.getText().to_owned(),
|
||||
"".to_owned(),
|
||||
))
|
||||
}
|
||||
|
||||
fn maybeWrap(value: Option<&str>) -> Option<Vec<String>> {
|
||||
if value.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(vec![value.unwrap().to_owned()])
|
||||
}
|
||||
}
|
||||
|
||||
fn unescapeBackslash(escaped: &str) -> String {
|
||||
let backslash = escaped.find('\\');
|
||||
if backslash.is_none() {
|
||||
return escaped.to_owned();
|
||||
}
|
||||
let max = escaped.len();
|
||||
let mut unescaped = String::with_capacity(max - 1);
|
||||
let backslash = backslash.unwrap_or(0);
|
||||
unescaped.push_str(&escaped[0..backslash]);
|
||||
let mut nextIsEscaped = false;
|
||||
for i in backslash..max {
|
||||
// for (int i = backslash; i < max; i++) {
|
||||
let c = escaped.chars().nth(i).unwrap();
|
||||
if nextIsEscaped || c != '\\' {
|
||||
unescaped.push(c);
|
||||
nextIsEscaped = false;
|
||||
} else {
|
||||
nextIsEscaped = true;
|
||||
}
|
||||
}
|
||||
|
||||
unescaped
|
||||
}
|
||||
|
||||
fn parseHexDigit(c: char) -> i32 {
|
||||
if c >= '0' && c <= '9' {
|
||||
return (c as u8 - '0' as u8) as i32;
|
||||
}
|
||||
if c >= 'a' && c <= 'f' {
|
||||
return 10 + (c as u8 - 'a' as u8) as i32;
|
||||
}
|
||||
if c >= 'A' && c <= 'F' {
|
||||
return 10 + (c as u8 - 'A' as u8) as i32;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
fn isStringOfDigits(value: &str, length: usize) -> bool {
|
||||
let matcher = Regex::new(Self::DIGITS).unwrap();
|
||||
!value.is_empty() && length > 0 && length == value.len() && matcher.is_match(value)
|
||||
}
|
||||
|
||||
fn isSubstringOfDigits(value: &str, offset: i32, length: usize) -> bool {
|
||||
if value.is_empty() || length <= 0 {
|
||||
return false;
|
||||
}
|
||||
let max = offset as usize + length;
|
||||
|
||||
let matcher = Regex::new(Self::DIGITS).unwrap();
|
||||
let sub_seq = &value[offset as usize..offset as usize + max];
|
||||
|
||||
value.len() >= max && matcher.is_match(sub_seq)
|
||||
}
|
||||
|
||||
fn parseNameValuePairs(uri: &str) -> Option<HashMap<String, String>> {
|
||||
let paramStart = uri.find('?');
|
||||
if paramStart.is_none() {
|
||||
return None;
|
||||
}
|
||||
let mut result = HashMap::with_capacity(3);
|
||||
let paramStart = paramStart.unwrap_or(0);
|
||||
|
||||
let sub_str = &uri[paramStart + 1..];
|
||||
let list = sub_str.split(Self::AMPERSAND);
|
||||
for keyValue in list {
|
||||
Self::appendKeyValue(keyValue, &mut result);
|
||||
}
|
||||
|
||||
// for keyValue in Self::AMPERSAND.split(uri[paramStart + 1..]) {
|
||||
// // for (String keyValue : AMPERSAND.split(uri.substring(paramStart + 1))) {
|
||||
// Self::appendKeyValue(keyValue, &mut result);
|
||||
// }
|
||||
Some(result)
|
||||
}
|
||||
|
||||
fn appendKeyValue(keyValue: &str, result: &mut HashMap<String, String>) {
|
||||
let keyValueTokens = keyValue.split(Self::EQUALS); //Self::EQUALS.split(keyValue, 2);
|
||||
|
||||
let kvp: Vec<&str> = keyValueTokens.take(2).collect();
|
||||
if let [key, value] = kvp[..] {
|
||||
let p_value = Self::urlDecode(value).unwrap_or("".to_owned());
|
||||
result.insert(key.to_owned(), p_value);
|
||||
}
|
||||
|
||||
// if keyValueTokens.len() == 2 {
|
||||
// let key = keyValueTokens[0];
|
||||
// let value = keyValueTokens[1];
|
||||
// try {
|
||||
// value = Self::urlDecode(value);
|
||||
// result.put(key, value);
|
||||
// } catch (IllegalArgumentException iae) {
|
||||
// // continue; invalid data such as an escape like %0t
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
fn urlDecode(encoded: &str) -> Result<String, Exceptions> {
|
||||
if let Ok(decoded) = decode(encoded) {
|
||||
Ok(decoded.to_string())
|
||||
} else {
|
||||
Err(Exceptions::IllegalStateException(
|
||||
"UnsupportedEncodingException".to_owned(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn matchPrefixedField(
|
||||
prefix: &str,
|
||||
rawText: &str,
|
||||
endChar: char,
|
||||
trim: bool,
|
||||
) -> Option<Vec<String>> {
|
||||
let mut matches: Vec<String> = Vec::new();
|
||||
let mut i = 0;
|
||||
let max = rawText.len();
|
||||
while i < max {
|
||||
i = if let Some(loc) = rawText[i..].find(prefix) {
|
||||
loc //rawText.indexOf(prefix, i);
|
||||
} else {
|
||||
break;
|
||||
};
|
||||
// if i < 0 {
|
||||
// break;
|
||||
// }
|
||||
i += prefix.len(); // Skip past this prefix we found to start
|
||||
let start = i; // Found the start of a match here
|
||||
let mut more = true;
|
||||
while more {
|
||||
let i = if let Some(loc) = rawText[i..].find(endChar) {
|
||||
if Self::countPrecedingBackslashes(rawText, i) % 2 != 0 {
|
||||
// semicolon was escaped (odd count of preceding backslashes) so continue
|
||||
i + 1
|
||||
} else {
|
||||
// found a match
|
||||
let mut element = Self::unescapeBackslash(&rawText[start..i + start]);
|
||||
if trim {
|
||||
element = element.to_string().trim().to_owned();
|
||||
}
|
||||
if !element.is_empty() {
|
||||
matches.push(element);
|
||||
}
|
||||
more = false;
|
||||
i + 1
|
||||
}
|
||||
} else {
|
||||
// No terminating end character? uh, done. Set i such that loop terminates and break
|
||||
//i = rawText.len();
|
||||
more = false;
|
||||
rawText.len()
|
||||
};
|
||||
}
|
||||
}
|
||||
if matches.is_empty() {
|
||||
return None;
|
||||
}
|
||||
Some(matches)
|
||||
}
|
||||
|
||||
fn countPrecedingBackslashes(s: &str, pos: usize) -> u32 {
|
||||
let mut count = 0;
|
||||
for i in (0..pos - 1).rev() {
|
||||
// for (int i = pos - 1; i >= 0; i--) {
|
||||
if s.chars().nth(i).unwrap() == '\\' {
|
||||
count += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
fn matchSinglePrefixedField(
|
||||
prefix: &str,
|
||||
rawText: &str,
|
||||
endChar: char,
|
||||
trim: bool,
|
||||
) -> Option<String> {
|
||||
let matches = Self::matchPrefixedField(prefix, rawText, endChar, trim);
|
||||
if let Some(m) = matches {
|
||||
Some(m[0].clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
// return matches == null ? null : matches[0];
|
||||
pub fn maybe_ppend_string(value: &str, result: &mut String) {
|
||||
if !value.is_empty() {
|
||||
result.push('\n');
|
||||
result.push_str(value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maybe_append_multiple(value: &[&str], result: &mut String) {
|
||||
if !value.is_empty() {
|
||||
for s in value {
|
||||
// for (String s : value) {
|
||||
result.push('\n');
|
||||
result.push_str(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maybeWrap(value: Option<&str>) -> Option<Vec<String>> {
|
||||
if value.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(vec![value.unwrap().to_owned()])
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unescapeBackslash(escaped: &str) -> String {
|
||||
let backslash = escaped.find('\\');
|
||||
if backslash.is_none() {
|
||||
return escaped.to_owned();
|
||||
}
|
||||
let max = escaped.len();
|
||||
let mut unescaped = String::with_capacity(max - 1);
|
||||
let backslash = backslash.unwrap_or(0);
|
||||
unescaped.push_str(&escaped[0..backslash]);
|
||||
let mut nextIsEscaped = false;
|
||||
for i in backslash..max {
|
||||
// for (int i = backslash; i < max; i++) {
|
||||
let c = escaped.chars().nth(i).unwrap();
|
||||
if nextIsEscaped || c != '\\' {
|
||||
unescaped.push(c);
|
||||
nextIsEscaped = false;
|
||||
} else {
|
||||
nextIsEscaped = true;
|
||||
}
|
||||
}
|
||||
|
||||
unescaped
|
||||
}
|
||||
|
||||
pub fn parseHexDigit(c: char) -> i32 {
|
||||
if c >= '0' && c <= '9' {
|
||||
return (c as u8 - '0' as u8) as i32;
|
||||
}
|
||||
if c >= 'a' && c <= 'f' {
|
||||
return 10 + (c as u8 - 'a' as u8) as i32;
|
||||
}
|
||||
if c >= 'A' && c <= 'F' {
|
||||
return 10 + (c as u8 - 'A' as u8) as i32;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
pub fn isStringOfDigits(value: &str, length: usize) -> bool {
|
||||
let matcher = Regex::new(DIGITS).unwrap();
|
||||
!value.is_empty() && length > 0 && length == value.len() && matcher.is_match(value)
|
||||
}
|
||||
|
||||
pub fn isSubstringOfDigits(value: &str, offset: i32, length: usize) -> bool {
|
||||
if value.is_empty() || length <= 0 {
|
||||
return false;
|
||||
}
|
||||
let max = offset as usize + length;
|
||||
|
||||
let matcher = Regex::new(DIGITS).unwrap();
|
||||
let sub_seq = &value[offset as usize..offset as usize + max];
|
||||
|
||||
value.len() >= max && matcher.is_match(sub_seq)
|
||||
}
|
||||
|
||||
pub fn parseNameValuePairs(uri: &str) -> Option<HashMap<String, String>> {
|
||||
let paramStart = uri.find('?');
|
||||
if paramStart.is_none() {
|
||||
return None;
|
||||
}
|
||||
let mut result = HashMap::with_capacity(3);
|
||||
let paramStart = paramStart.unwrap_or(0);
|
||||
|
||||
let sub_str = &uri[paramStart + 1..];
|
||||
let list = sub_str.split(AMPERSAND);
|
||||
for keyValue in list {
|
||||
appendKeyValue(keyValue, &mut result);
|
||||
}
|
||||
|
||||
// for keyValue in Self::AMPERSAND.split(uri[paramStart + 1..]) {
|
||||
// // for (String keyValue : AMPERSAND.split(uri.substring(paramStart + 1))) {
|
||||
// Self::appendKeyValue(keyValue, &mut result);
|
||||
// }
|
||||
Some(result)
|
||||
}
|
||||
|
||||
pub fn appendKeyValue(keyValue: &str, result: &mut HashMap<String, String>) {
|
||||
let keyValueTokens = keyValue.split(EQUALS); //Self::EQUALS.split(keyValue, 2);
|
||||
|
||||
let kvp: Vec<&str> = keyValueTokens.take(2).collect();
|
||||
if let [key, value] = kvp[..] {
|
||||
let p_value = urlDecode(value).unwrap_or("".to_owned());
|
||||
result.insert(key.to_owned(), p_value);
|
||||
}
|
||||
|
||||
// if keyValueTokens.len() == 2 {
|
||||
// let key = keyValueTokens[0];
|
||||
// let value = keyValueTokens[1];
|
||||
// try {
|
||||
// value = Self::urlDecode(value);
|
||||
// result.put(key, value);
|
||||
// } catch (IllegalArgumentException iae) {
|
||||
// // continue; invalid data such as an escape like %0t
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn urlDecode(encoded: &str) -> Result<String, Exceptions> {
|
||||
if let Ok(decoded) = decode(encoded) {
|
||||
Ok(decoded.to_string())
|
||||
} else {
|
||||
Err(Exceptions::IllegalStateException(
|
||||
"UnsupportedEncodingException".to_owned(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn matchPrefixedField(
|
||||
prefix: &str,
|
||||
rawText: &str,
|
||||
endChar: char,
|
||||
trim: bool,
|
||||
) -> Option<Vec<String>> {
|
||||
let mut matches: Vec<String> = Vec::new();
|
||||
let mut i = 0;
|
||||
let max = rawText.len();
|
||||
while i < max {
|
||||
i = if let Some(loc) = rawText[i..].find(prefix) {
|
||||
loc //rawText.indexOf(prefix, i);
|
||||
} else {
|
||||
break;
|
||||
};
|
||||
// if i < 0 {
|
||||
// break;
|
||||
// }
|
||||
i += prefix.len(); // Skip past this prefix we found to start
|
||||
let start = i; // Found the start of a match here
|
||||
let mut more = true;
|
||||
while more {
|
||||
let i = if let Some(loc) = rawText[i..].find(endChar) {
|
||||
if countPrecedingBackslashes(rawText, i) % 2 != 0 {
|
||||
// semicolon was escaped (odd count of preceding backslashes) so continue
|
||||
i + 1
|
||||
} else {
|
||||
// found a match
|
||||
let mut element = unescapeBackslash(&rawText[start..i + start]);
|
||||
if trim {
|
||||
element = element.to_string().trim().to_owned();
|
||||
}
|
||||
if !element.is_empty() {
|
||||
matches.push(element);
|
||||
}
|
||||
more = false;
|
||||
i + 1
|
||||
}
|
||||
} else {
|
||||
// No terminating end character? uh, done. Set i such that loop terminates and break
|
||||
//i = rawText.len();
|
||||
more = false;
|
||||
rawText.len()
|
||||
};
|
||||
}
|
||||
}
|
||||
if matches.is_empty() {
|
||||
return None;
|
||||
}
|
||||
Some(matches)
|
||||
}
|
||||
|
||||
pub fn countPrecedingBackslashes(s: &str, pos: usize) -> u32 {
|
||||
let mut count = 0;
|
||||
for i in (0..pos - 1).rev() {
|
||||
// for (int i = pos - 1; i >= 0; i--) {
|
||||
if s.chars().nth(i).unwrap() == '\\' {
|
||||
count += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
pub fn matchSinglePrefixedField(
|
||||
prefix: &str,
|
||||
rawText: &str,
|
||||
endChar: char,
|
||||
trim: bool,
|
||||
) -> Option<String> {
|
||||
let matches = matchPrefixedField(prefix, rawText, endChar, trim);
|
||||
if let Some(m) = matches {
|
||||
Some(m[0].clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
// return matches == null ? null : matches[0];
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 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.client.result;
|
||||
|
||||
/**
|
||||
* Represents a parsed result that encodes a telephone number.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class TelParsedRXingResult extends ParsedRXingResult {
|
||||
|
||||
private final String number;
|
||||
private final String telURI;
|
||||
private final String title;
|
||||
|
||||
public TelParsedRXingResult(String number, String telURI, String title) {
|
||||
super(ParsedRXingResultType.TEL);
|
||||
this.number = number;
|
||||
this.telURI = telURI;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public String getTelURI() {
|
||||
return telURI;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayRXingResult() {
|
||||
StringBuilder result = new StringBuilder(20);
|
||||
maybeAppend(number, result);
|
||||
maybeAppend(title, result);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
}
|
||||
64
src/client/result/TelParsedResult.rs
Normal file
64
src/client/result/TelParsedResult.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2008 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.client.result;
|
||||
|
||||
use super::{ParsedRXingResult, ParsedRXingResultType};
|
||||
|
||||
/**
|
||||
* Represents a parsed result that encodes a telephone number.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
pub struct TelParsedRXingResult {
|
||||
number: String,
|
||||
telURI: String,
|
||||
title: String,
|
||||
}
|
||||
|
||||
impl ParsedRXingResult for TelParsedRXingResult {
|
||||
fn getType(&self) -> super::ParsedRXingResultType {
|
||||
ParsedRXingResultType::TEL
|
||||
}
|
||||
|
||||
fn getDisplayRXingResult(&self) -> String {
|
||||
let mut result = String::with_capacity(20);
|
||||
self.maybe_append(&self.number, &mut result);
|
||||
self.maybe_append(&self.title, &mut result);
|
||||
result
|
||||
}
|
||||
}
|
||||
impl TelParsedRXingResult {
|
||||
pub fn new(number: String, telURI: String, title: String) -> Self {
|
||||
Self {
|
||||
number,
|
||||
telURI,
|
||||
title,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getNumber(&self) -> &str {
|
||||
&self.number
|
||||
}
|
||||
|
||||
pub fn getTelURI(&self) -> &str {
|
||||
&self.telURI
|
||||
}
|
||||
|
||||
pub fn getTitle(&self) -> &str {
|
||||
&&self.title
|
||||
}
|
||||
}
|
||||
@@ -1,47 +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.client.result;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.RXingResult;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests {@link TelParsedRXingResult}.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class TelParsedRXingResultTestCase extends Assert {
|
||||
|
||||
@Test
|
||||
public void testTel() {
|
||||
doTest("tel:+15551212", "+15551212", null);
|
||||
doTest("tel:2125551212", "2125551212", null);
|
||||
}
|
||||
|
||||
private static void doTest(String contents, String number, String title) {
|
||||
RXingResult fakeRXingResult = new RXingResult(contents, null, null, BarcodeFormat.QR_CODE);
|
||||
ParsedRXingResult result = RXingResultParser.parseRXingResult(fakeRXingResult);
|
||||
assertSame(ParsedRXingResultType.TEL, result.getType());
|
||||
TelParsedRXingResult telRXingResult = (TelParsedRXingResult) result;
|
||||
assertEquals(number, telRXingResult.getNumber());
|
||||
assertEquals(title, telRXingResult.getTitle());
|
||||
assertEquals("tel:" + number, telRXingResult.getTelURI());
|
||||
}
|
||||
|
||||
}
|
||||
63
src/client/result/TelParsedResultTestCase.rs
Normal file
63
src/client/result/TelParsedResultTestCase.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.client.result;
|
||||
|
||||
// import com.google.zxing.BarcodeFormat;
|
||||
// import com.google.zxing.RXingResult;
|
||||
// import org.junit.Assert;
|
||||
// import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests {@link TelParsedRXingResult}.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
// public final class TelParsedRXingResultTestCase extends Assert {
|
||||
use std::any::Any;
|
||||
|
||||
use crate::{
|
||||
client::result::{
|
||||
ParsedClientResult, ParsedRXingResult, ParsedRXingResultType, RXingResultParser,
|
||||
TelParsedRXingResult,
|
||||
},
|
||||
BarcodeFormat, RXingResult,
|
||||
};
|
||||
|
||||
use super::ResultParser;
|
||||
|
||||
#[test]
|
||||
fn testTel() {
|
||||
doTest("tel:+15551212", "+15551212", "");
|
||||
doTest("tel:2125551212", "2125551212", "");
|
||||
}
|
||||
|
||||
fn doTest(contents: &str, number: &str, title: &str) {
|
||||
let fakeRXingResult =
|
||||
RXingResult::new(contents, Vec::new(), Vec::new(), BarcodeFormat::QR_CODE);
|
||||
let result = ResultParser::parseRXingResult(&fakeRXingResult);
|
||||
|
||||
if let ParsedClientResult::TelResult(telRXingResult) = result {
|
||||
assert_eq!(ParsedRXingResultType::TEL, telRXingResult.getType());
|
||||
assert_eq!(number, telRXingResult.getNumber());
|
||||
assert_eq!(title, telRXingResult.getTitle());
|
||||
assert_eq!(format!("tel:{}", number), telRXingResult.getTelURI());
|
||||
} else {
|
||||
panic!("wrong return type, expected TelResult");
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 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.client.result;
|
||||
|
||||
import com.google.zxing.RXingResult;
|
||||
|
||||
/**
|
||||
* Parses a "tel:" URI result, which specifies a phone number.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class TelRXingResultParser extends RXingResultParser {
|
||||
|
||||
@Override
|
||||
public TelParsedRXingResult parse(RXingResult result) {
|
||||
String rawText = getMassagedText(result);
|
||||
if (!rawText.startsWith("tel:") && !rawText.startsWith("TEL:")) {
|
||||
return null;
|
||||
}
|
||||
// Normalize "TEL:" to "tel:"
|
||||
String telURI = rawText.startsWith("TEL:") ? "tel:" + rawText.substring(4) : rawText;
|
||||
// Drop tel, query portion
|
||||
int queryStart = rawText.indexOf('?', 4);
|
||||
String number = queryStart < 0 ? rawText.substring(4) : rawText.substring(4, queryStart);
|
||||
return new TelParsedRXingResult(number, telURI, null);
|
||||
}
|
||||
|
||||
}
|
||||
49
src/client/result/TelResultParser.rs
Normal file
49
src/client/result/TelResultParser.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2008 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.client.result;
|
||||
|
||||
// import com.google.zxing.RXingResult;
|
||||
|
||||
use super::{RXingResultParser, TelParsedRXingResult, ParsedRXingResult, ParsedClientResult, ResultParser};
|
||||
|
||||
/**
|
||||
* Parses a "tel:" URI result, which specifies a phone number.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
pub struct TelRXingResultParser {}
|
||||
|
||||
impl RXingResultParser for TelRXingResultParser {
|
||||
|
||||
fn parse(&self, theRXingResult: &crate::RXingResult) -> Option<ParsedClientResult> {
|
||||
let rawText = ResultParser::getMassagedText(theRXingResult);
|
||||
if !rawText.starts_with("tel:") && !rawText.starts_with("TEL:") {
|
||||
return None;
|
||||
}
|
||||
// Normalize "TEL:" to "tel:"
|
||||
let telURI = if rawText.starts_with("TEL:") {format!("tel:{}", &rawText[4..])} else {rawText.clone()};
|
||||
// Drop tel, query portion
|
||||
let queryStart = rawText[4..].find('?');
|
||||
let number = if let Some(v) = queryStart {
|
||||
&rawText[4..v+4]
|
||||
}else {
|
||||
&rawText[4..]
|
||||
};
|
||||
// let number = queryStart < 0 ? : ;
|
||||
Some(ParsedClientResult::TelResult(TelParsedRXingResult::new(number.to_owned(), telURI.to_owned(), "".to_owned())))
|
||||
}
|
||||
}
|
||||
@@ -14,36 +14,41 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.zxing.client.result;
|
||||
// package com.google.zxing.client.result;
|
||||
|
||||
use super::{ParsedRXingResult, ParsedRXingResultType};
|
||||
|
||||
/**
|
||||
* A simple result type encapsulating a string that has no further
|
||||
* interpretation.
|
||||
*
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class TextParsedRXingResult extends ParsedRXingResult {
|
||||
|
||||
private final String text;
|
||||
private final String language;
|
||||
|
||||
public TextParsedRXingResult(String text, String language) {
|
||||
super(ParsedRXingResultType.TEXT);
|
||||
this.text = text;
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayRXingResult() {
|
||||
return text;
|
||||
}
|
||||
|
||||
pub struct TextParsedRXingResult {
|
||||
text: String,
|
||||
language: String,
|
||||
}
|
||||
|
||||
impl ParsedRXingResult for TextParsedRXingResult {
|
||||
fn getType(&self) -> ParsedRXingResultType {
|
||||
ParsedRXingResultType::TEXT
|
||||
}
|
||||
|
||||
fn getDisplayRXingResult(&self) -> String {
|
||||
self.text.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl TextParsedRXingResult {
|
||||
pub fn new(text: String, language: String) -> Self {
|
||||
Self { text, language }
|
||||
}
|
||||
|
||||
pub fn getText(&self) -> &str {
|
||||
&self.text
|
||||
}
|
||||
|
||||
pub fn getLanguage(&self) -> &str {
|
||||
&self.language
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,21 @@
|
||||
mod ParsedResult;
|
||||
pub use ParsedResult::*;
|
||||
mod ResultParser;
|
||||
|
||||
mod TelParsedResult;
|
||||
mod TextParsedResult;
|
||||
mod ParsedResultType;
|
||||
mod TelResultParser;
|
||||
|
||||
pub use ParsedResultType::*;
|
||||
pub use ResultParser::*;
|
||||
pub use ResultParser::*;
|
||||
pub use TelParsedResult::*;
|
||||
pub use TextParsedResult::*;
|
||||
pub use ParsedResult::*;
|
||||
pub use TelResultParser::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod TelParsedResultTestCase;
|
||||
|
||||
pub enum ParsedClientResult {
|
||||
TextResult(TextParsedRXingResult),
|
||||
TelResult(TelParsedRXingResult)
|
||||
}
|
||||
Reference in New Issue
Block a user