mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 12:22:34 +00:00
still working through addresses
This commit is contained in:
@@ -1,89 +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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Implements KDDI AU's address book format. See
|
||||
* <a href="http://www.au.kddi.com/ezfactory/tec/two_dimensions/index.html">
|
||||
* http://www.au.kddi.com/ezfactory/tec/two_dimensions/index.html</a>.
|
||||
* (Thanks to Yuzo for translating!)
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class AddressBookAURXingResultParser extends RXingResultParser {
|
||||
|
||||
@Override
|
||||
public AddressBookParsedRXingResult parse(RXingResult result) {
|
||||
String rawText = getMassagedText(result);
|
||||
// MEMORY is mandatory; seems like a decent indicator, as does end-of-record separator CR/LF
|
||||
if (!rawText.contains("MEMORY") || !rawText.contains("\r\n")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// NAME1 and NAME2 have specific uses, namely written name and pronunciation, respectively.
|
||||
// Therefore we treat them specially instead of as an array of names.
|
||||
String name = matchSinglePrefixedField("NAME1:", rawText, '\r', true);
|
||||
String pronunciation = matchSinglePrefixedField("NAME2:", rawText, '\r', true);
|
||||
|
||||
String[] phoneNumbers = matchMultipleValuePrefix("TEL", rawText);
|
||||
String[] emails = matchMultipleValuePrefix("MAIL", rawText);
|
||||
String note = matchSinglePrefixedField("MEMORY:", rawText, '\r', false);
|
||||
String address = matchSinglePrefixedField("ADD:", rawText, '\r', true);
|
||||
String[] addresses = address == null ? null : new String[] {address};
|
||||
return new AddressBookParsedRXingResult(maybeWrap(name),
|
||||
null,
|
||||
pronunciation,
|
||||
phoneNumbers,
|
||||
null,
|
||||
emails,
|
||||
null,
|
||||
null,
|
||||
note,
|
||||
addresses,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
private static String[] matchMultipleValuePrefix(String prefix, String rawText) {
|
||||
List<String> values = null;
|
||||
// For now, always 3, and always trim
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
String value = matchSinglePrefixedField(prefix + i + ':', rawText, '\r', true);
|
||||
if (value == null) {
|
||||
break;
|
||||
}
|
||||
if (values == null) {
|
||||
values = new ArrayList<>(3); // lazy init
|
||||
}
|
||||
values.add(value);
|
||||
}
|
||||
if (values == null) {
|
||||
return null;
|
||||
}
|
||||
return values.toArray(EMPTY_STR_ARRAY);
|
||||
}
|
||||
|
||||
}
|
||||
99
src/client/result/AddressBookAUResultParser.rs
Normal file
99
src/client/result/AddressBookAUResultParser.rs
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
// import java.util.ArrayList;
|
||||
// import java.util.List;
|
||||
|
||||
use crate::RXingResult;
|
||||
|
||||
use super::{AddressBookParsedRXingResult, ParsedClientResult, ResultParser};
|
||||
|
||||
/**
|
||||
* Implements KDDI AU's address book format. See
|
||||
* <a href="http://www.au.kddi.com/ezfactory/tec/two_dimensions/index.html">
|
||||
* http://www.au.kddi.com/ezfactory/tec/two_dimensions/index.html</a>.
|
||||
* (Thanks to Yuzo for translating!)
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
let rawText = ResultParser::getMassagedText(result);
|
||||
// MEMORY is mandatory; seems like a decent indicator, as does end-of-record separator CR/LF
|
||||
if !rawText.contains("MEMORY") || !rawText.contains("\r\n") {
|
||||
return None;
|
||||
}
|
||||
|
||||
// NAME1 and NAME2 have specific uses, namely written name and pronunciation, respectively.
|
||||
// Therefore we treat them specially instead of as an array of names.
|
||||
let name = ResultParser::matchSinglePrefixedField("NAME1:", &rawText, '\r', true);
|
||||
let pronunciation = ResultParser::matchSinglePrefixedField("NAME2:", &rawText, '\r', true);
|
||||
|
||||
let phoneNumbers = matchMultipleValuePrefix("TEL", &rawText);
|
||||
let emails = matchMultipleValuePrefix("MAIL", &rawText);
|
||||
let note = ResultParser::matchSinglePrefixedField("MEMORY:", &rawText, '\r', false)?;
|
||||
let address = ResultParser::matchSinglePrefixedField("ADD:", &rawText, '\r', true);
|
||||
let addresses = if address.is_none() {
|
||||
Vec::new()
|
||||
} else {
|
||||
vec![address?]
|
||||
};
|
||||
if let Ok(new_data) = AddressBookParsedRXingResult::with_details(
|
||||
ResultParser::maybeWrap(name)?,
|
||||
Vec::new(),
|
||||
"".to_owned(),
|
||||
phoneNumbers,
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
"".to_owned(),
|
||||
note,
|
||||
addresses,
|
||||
Vec::new(),
|
||||
"".to_owned(),
|
||||
"".to_owned(),
|
||||
"".to_owned(),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
) {
|
||||
Some(ParsedClientResult::AddressBookResult(new_data))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn matchMultipleValuePrefix(prefix: &str, rawText: &str) -> Vec<String> {
|
||||
let mut values = Vec::new();
|
||||
// For now, always 3, and always trim
|
||||
for i in 1..=3 {
|
||||
// for (int i = 1; i <= 3; i++) {
|
||||
let value = ResultParser::matchSinglePrefixedField(
|
||||
&format!("{}{}:", prefix, i),
|
||||
rawText,
|
||||
'\r',
|
||||
true,
|
||||
);
|
||||
if value.is_none() {
|
||||
break;
|
||||
}
|
||||
values.push(value.unwrap());
|
||||
}
|
||||
|
||||
values
|
||||
}
|
||||
@@ -1,92 +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.RXingResult;
|
||||
|
||||
/**
|
||||
* Implements the "MECARD" address book entry format.
|
||||
*
|
||||
* Supported keys: N, SOUND, TEL, EMAIL, NOTE, ADR, BDAY, URL, plus ORG
|
||||
* Unsupported keys: TEL-AV, NICKNAME
|
||||
*
|
||||
* Except for TEL, multiple values for keys are also not supported;
|
||||
* the first one found takes precedence.
|
||||
*
|
||||
* Our understanding of the MECARD format is based on this document:
|
||||
*
|
||||
* http://www.mobicode.org.tw/files/OMIA%20Mobile%20Bar%20Code%20Standard%20v3.2.1.doc
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class AddressBookDoCoMoRXingResultParser extends AbstractDoCoMoRXingResultParser {
|
||||
|
||||
@Override
|
||||
public AddressBookParsedRXingResult parse(RXingResult result) {
|
||||
String rawText = getMassagedText(result);
|
||||
if (!rawText.startsWith("MECARD:")) {
|
||||
return null;
|
||||
}
|
||||
String[] rawName = matchDoCoMoPrefixedField("N:", rawText);
|
||||
if (rawName == null) {
|
||||
return null;
|
||||
}
|
||||
String name = parseName(rawName[0]);
|
||||
String pronunciation = matchSingleDoCoMoPrefixedField("SOUND:", rawText, true);
|
||||
String[] phoneNumbers = matchDoCoMoPrefixedField("TEL:", rawText);
|
||||
String[] emails = matchDoCoMoPrefixedField("EMAIL:", rawText);
|
||||
String note = matchSingleDoCoMoPrefixedField("NOTE:", rawText, false);
|
||||
String[] addresses = matchDoCoMoPrefixedField("ADR:", rawText);
|
||||
String birthday = matchSingleDoCoMoPrefixedField("BDAY:", rawText, true);
|
||||
if (!isStringOfDigits(birthday, 8)) {
|
||||
// No reason to throw out the whole card because the birthday is formatted wrong.
|
||||
birthday = null;
|
||||
}
|
||||
String[] urls = matchDoCoMoPrefixedField("URL:", rawText);
|
||||
|
||||
// Although ORG may not be strictly legal in MECARD, it does exist in VCARD and we might as well
|
||||
// honor it when found in the wild.
|
||||
String org = matchSingleDoCoMoPrefixedField("ORG:", rawText, true);
|
||||
|
||||
return new AddressBookParsedRXingResult(maybeWrap(name),
|
||||
null,
|
||||
pronunciation,
|
||||
phoneNumbers,
|
||||
null,
|
||||
emails,
|
||||
null,
|
||||
null,
|
||||
note,
|
||||
addresses,
|
||||
null,
|
||||
org,
|
||||
birthday,
|
||||
null,
|
||||
urls,
|
||||
null);
|
||||
}
|
||||
|
||||
private static String parseName(String name) {
|
||||
int comma = name.indexOf(',');
|
||||
if (comma >= 0) {
|
||||
// Format may be last,first; switch it around
|
||||
return name.substring(comma + 1) + ' ' + name.substring(0, comma);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
111
src/client/result/AddressBookDoCoMoResultParser.rs
Normal file
111
src/client/result/AddressBookDoCoMoResultParser.rs
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.RXingResult;
|
||||
|
||||
use crate::RXingResult;
|
||||
|
||||
use super::{AddressBookParsedRXingResult, ParsedClientResult, ResultParser};
|
||||
|
||||
/**
|
||||
* Implements the "MECARD" address book entry format.
|
||||
*
|
||||
* Supported keys: N, SOUND, TEL, EMAIL, NOTE, ADR, BDAY, URL, plus ORG
|
||||
* Unsupported keys: TEL-AV, NICKNAME
|
||||
*
|
||||
* Except for TEL, multiple values for keys are also not supported;
|
||||
* the first one found takes precedence.
|
||||
*
|
||||
* Our understanding of the MECARD format is based on this document:
|
||||
*
|
||||
* http://www.mobicode.org.tw/files/OMIA%20Mobile%20Bar%20Code%20Standard%20v3.2.1.doc
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
// public final class AddressBookDoCoMoRXingResultParser extends AbstractDoCoMoRXingResultParser {
|
||||
pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
let rawText = ResultParser::getMassagedText(result);
|
||||
if !rawText.starts_with("MECARD:") {
|
||||
return None;
|
||||
}
|
||||
let rawName = ResultParser::match_do_co_mo_prefixed_field("N:", &rawText)?;
|
||||
|
||||
let name = parseName(&rawName[0]);
|
||||
let pronunciation =
|
||||
ResultParser::match_single_do_co_mo_prefixed_field("SOUND:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
let phoneNumbers =
|
||||
ResultParser::match_do_co_mo_prefixed_field("TEL:", &rawText).unwrap_or_default();
|
||||
let emails =
|
||||
ResultParser::match_do_co_mo_prefixed_field("EMAIL:", &rawText).unwrap_or_default();
|
||||
let note = ResultParser::match_single_do_co_mo_prefixed_field("NOTE:", &rawText, false)
|
||||
.unwrap_or_default();
|
||||
let addresses =
|
||||
ResultParser::match_do_co_mo_prefixed_field("ADR:", &rawText).unwrap_or_default();
|
||||
let mut birthday = ResultParser::match_single_do_co_mo_prefixed_field("BDAY:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
if !ResultParser::isStringOfDigits(&birthday, 8) {
|
||||
// No reason to throw out the whole card because the birthday is formatted wrong.
|
||||
birthday = "".to_owned();
|
||||
}
|
||||
let urls = ResultParser::match_do_co_mo_prefixed_field("URL:", &rawText).unwrap_or_default();
|
||||
|
||||
// Although ORG may not be strictly legal in MECARD, it does exist in VCARD and we might as well
|
||||
// honor it when found in the wild.
|
||||
let org = ResultParser::match_single_do_co_mo_prefixed_field("ORG:", &rawText, true)
|
||||
.unwrap_or_default();
|
||||
|
||||
if let Ok(new_adb) = AddressBookParsedRXingResult::with_details(
|
||||
ResultParser::maybeWrap(Some(name))?,
|
||||
Vec::new(),
|
||||
pronunciation,
|
||||
phoneNumbers,
|
||||
Vec::new(),
|
||||
emails,
|
||||
Vec::new(),
|
||||
"".to_owned(),
|
||||
note,
|
||||
addresses,
|
||||
Vec::new(),
|
||||
org,
|
||||
birthday,
|
||||
"".to_owned(),
|
||||
urls,
|
||||
Vec::new(),
|
||||
) {
|
||||
Some(ParsedClientResult::AddressBookResult(new_adb))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn parseName(name: &str) -> String {
|
||||
if let Some(comma) = name.find(',') {
|
||||
format!("{} {}", &name[comma + 1..], &name[0..comma])
|
||||
} else {
|
||||
name.to_owned()
|
||||
}
|
||||
// let comma = name.indexOf(',');
|
||||
// if (comma >= 0) {
|
||||
// // Format may be last,first; switch it around
|
||||
// return name.substring(comma + 1) + ' ' + name.substring(0, comma);
|
||||
// }
|
||||
// return name;
|
||||
}
|
||||
|
||||
// }
|
||||
@@ -1,220 +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;
|
||||
|
||||
/**
|
||||
* Represents a parsed result that encodes contact information, like that in an address book
|
||||
* entry.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class AddressBookParsedRXingResult extends ParsedRXingResult {
|
||||
|
||||
private final String[] names;
|
||||
private final String[] nicknames;
|
||||
private final String pronunciation;
|
||||
private final String[] phoneNumbers;
|
||||
private final String[] phoneTypes;
|
||||
private final String[] emails;
|
||||
private final String[] emailTypes;
|
||||
private final String instantMessenger;
|
||||
private final String note;
|
||||
private final String[] addresses;
|
||||
private final String[] addressTypes;
|
||||
private final String org;
|
||||
private final String birthday;
|
||||
private final String title;
|
||||
private final String[] urls;
|
||||
private final String[] geo;
|
||||
|
||||
public AddressBookParsedRXingResult(String[] names,
|
||||
String[] phoneNumbers,
|
||||
String[] phoneTypes,
|
||||
String[] emails,
|
||||
String[] emailTypes,
|
||||
String[] addresses,
|
||||
String[] addressTypes) {
|
||||
this(names,
|
||||
null,
|
||||
null,
|
||||
phoneNumbers,
|
||||
phoneTypes,
|
||||
emails,
|
||||
emailTypes,
|
||||
null,
|
||||
null,
|
||||
addresses,
|
||||
addressTypes,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
public AddressBookParsedRXingResult(String[] names,
|
||||
String[] nicknames,
|
||||
String pronunciation,
|
||||
String[] phoneNumbers,
|
||||
String[] phoneTypes,
|
||||
String[] emails,
|
||||
String[] emailTypes,
|
||||
String instantMessenger,
|
||||
String note,
|
||||
String[] addresses,
|
||||
String[] addressTypes,
|
||||
String org,
|
||||
String birthday,
|
||||
String title,
|
||||
String[] urls,
|
||||
String[] geo) {
|
||||
super(ParsedRXingResultType.ADDRESSBOOK);
|
||||
if (phoneNumbers != null && phoneTypes != null && phoneNumbers.length != phoneTypes.length) {
|
||||
throw new IllegalArgumentException("Phone numbers and types lengths differ");
|
||||
}
|
||||
if (emails != null && emailTypes != null && emails.length != emailTypes.length) {
|
||||
throw new IllegalArgumentException("Emails and types lengths differ");
|
||||
}
|
||||
if (addresses != null && addressTypes != null && addresses.length != addressTypes.length) {
|
||||
throw new IllegalArgumentException("Addresses and types lengths differ");
|
||||
}
|
||||
this.names = names;
|
||||
this.nicknames = nicknames;
|
||||
this.pronunciation = pronunciation;
|
||||
this.phoneNumbers = phoneNumbers;
|
||||
this.phoneTypes = phoneTypes;
|
||||
this.emails = emails;
|
||||
this.emailTypes = emailTypes;
|
||||
this.instantMessenger = instantMessenger;
|
||||
this.note = note;
|
||||
this.addresses = addresses;
|
||||
this.addressTypes = addressTypes;
|
||||
this.org = org;
|
||||
this.birthday = birthday;
|
||||
this.title = title;
|
||||
this.urls = urls;
|
||||
this.geo = geo;
|
||||
}
|
||||
|
||||
public String[] getNames() {
|
||||
return names;
|
||||
}
|
||||
|
||||
public String[] getNicknames() {
|
||||
return nicknames;
|
||||
}
|
||||
|
||||
/**
|
||||
* In Japanese, the name is written in kanji, which can have multiple readings. Therefore a hint
|
||||
* is often provided, called furigana, which spells the name phonetically.
|
||||
*
|
||||
* @return The pronunciation of the getNames() field, often in hiragana or katakana.
|
||||
*/
|
||||
public String getPronunciation() {
|
||||
return pronunciation;
|
||||
}
|
||||
|
||||
public String[] getPhoneNumbers() {
|
||||
return phoneNumbers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return optional descriptions of the type of each phone number. It could be like "HOME", but,
|
||||
* there is no guaranteed or standard format.
|
||||
*/
|
||||
public String[] getPhoneTypes() {
|
||||
return phoneTypes;
|
||||
}
|
||||
|
||||
public String[] getEmails() {
|
||||
return emails;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return optional descriptions of the type of each e-mail. It could be like "WORK", but,
|
||||
* there is no guaranteed or standard format.
|
||||
*/
|
||||
public String[] getEmailTypes() {
|
||||
return emailTypes;
|
||||
}
|
||||
|
||||
public String getInstantMessenger() {
|
||||
return instantMessenger;
|
||||
}
|
||||
|
||||
public String getNote() {
|
||||
return note;
|
||||
}
|
||||
|
||||
public String[] getAddresses() {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return optional descriptions of the type of each e-mail. It could be like "WORK", but,
|
||||
* there is no guaranteed or standard format.
|
||||
*/
|
||||
public String[] getAddressTypes() {
|
||||
return addressTypes;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getOrg() {
|
||||
return org;
|
||||
}
|
||||
|
||||
public String[] getURLs() {
|
||||
return urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return birthday formatted as yyyyMMdd (e.g. 19780917)
|
||||
*/
|
||||
public String getBirthday() {
|
||||
return birthday;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a location as a latitude/longitude pair
|
||||
*/
|
||||
public String[] getGeo() {
|
||||
return geo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayRXingResult() {
|
||||
StringBuilder result = new StringBuilder(100);
|
||||
maybeAppend(names, result);
|
||||
maybeAppend(nicknames, result);
|
||||
maybeAppend(pronunciation, result);
|
||||
maybeAppend(title, result);
|
||||
maybeAppend(org, result);
|
||||
maybeAppend(addresses, result);
|
||||
maybeAppend(phoneNumbers, result);
|
||||
maybeAppend(emails, result);
|
||||
maybeAppend(instantMessenger, result);
|
||||
maybeAppend(urls, result);
|
||||
maybeAppend(birthday, result);
|
||||
maybeAppend(geo, result);
|
||||
maybeAppend(note, result);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
}
|
||||
242
src/client/result/AddressBookParsedResult.rs
Normal file
242
src/client/result/AddressBookParsedResult.rs
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
use crate::exceptions::Exceptions;
|
||||
|
||||
use super::{ParsedRXingResult, ParsedRXingResultType, ResultParser};
|
||||
|
||||
/**
|
||||
* Represents a parsed result that encodes contact information, like that in an address book
|
||||
* entry.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
pub struct AddressBookParsedRXingResult {
|
||||
names: Vec<String>,
|
||||
nicknames: Vec<String>,
|
||||
pronunciation: String,
|
||||
phone_numbers: Vec<String>,
|
||||
phone_types: Vec<String>,
|
||||
emails: Vec<String>,
|
||||
email_types: Vec<String>,
|
||||
instant_messenger: String,
|
||||
note: String,
|
||||
addresses: Vec<String>,
|
||||
address_types: Vec<String>,
|
||||
org: String,
|
||||
birthday: String,
|
||||
title: String,
|
||||
urls: Vec<String>,
|
||||
geo: Vec<String>,
|
||||
}
|
||||
impl ParsedRXingResult for AddressBookParsedRXingResult {
|
||||
fn getType(&self) -> super::ParsedRXingResultType {
|
||||
ParsedRXingResultType::ADDRESSBOOK
|
||||
}
|
||||
|
||||
fn getDisplayRXingResult(&self) -> String {
|
||||
let mut result = String::with_capacity(100);
|
||||
|
||||
ResultParser::maybe_append_multiple(&self.names, &mut result);
|
||||
ResultParser::maybe_append_multiple(&self.nicknames, &mut result);
|
||||
ResultParser::maybe_append_string(&self.pronunciation, &mut result);
|
||||
ResultParser::maybe_append_string(&self.title, &mut result);
|
||||
ResultParser::maybe_append_string(&self.org, &mut result);
|
||||
ResultParser::maybe_append_multiple(&self.addresses, &mut result);
|
||||
ResultParser::maybe_append_multiple(&self.phone_numbers, &mut result);
|
||||
ResultParser::maybe_append_multiple(&self.emails, &mut result);
|
||||
ResultParser::maybe_append_string(&self.instant_messenger, &mut result);
|
||||
ResultParser::maybe_append_multiple(&self.urls, &mut result);
|
||||
ResultParser::maybe_append_string(&self.birthday, &mut result);
|
||||
ResultParser::maybe_append_multiple(&self.geo, &mut result);
|
||||
ResultParser::maybe_append_string(&self.note, &mut result);
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
impl AddressBookParsedRXingResult {
|
||||
pub fn new(
|
||||
names: Vec<String>,
|
||||
phone_numbers: Vec<String>,
|
||||
phone_types: Vec<String>,
|
||||
emails: Vec<String>,
|
||||
email_types: Vec<String>,
|
||||
addresses: Vec<String>,
|
||||
address_types: Vec<String>,
|
||||
) -> Result<Self, Exceptions> {
|
||||
Self::with_details(
|
||||
names,
|
||||
Vec::new(),
|
||||
"".to_owned(),
|
||||
phone_numbers,
|
||||
phone_types,
|
||||
emails,
|
||||
email_types,
|
||||
"".to_owned(),
|
||||
"".to_owned(),
|
||||
addresses,
|
||||
address_types,
|
||||
"".to_owned(),
|
||||
"".to_owned(),
|
||||
"".to_owned(),
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn with_details(
|
||||
names: Vec<String>,
|
||||
nicknames: Vec<String>,
|
||||
pronunciation: String,
|
||||
phone_numbers: Vec<String>,
|
||||
phone_types: Vec<String>,
|
||||
emails: Vec<String>,
|
||||
email_types: Vec<String>,
|
||||
instant_messenger: String,
|
||||
note: String,
|
||||
addresses: Vec<String>,
|
||||
address_types: Vec<String>,
|
||||
org: String,
|
||||
birthday: String,
|
||||
title: String,
|
||||
urls: Vec<String>,
|
||||
geo: Vec<String>,
|
||||
) -> Result<Self, Exceptions> {
|
||||
if phone_numbers.len() != phone_types.len() {
|
||||
return Err(Exceptions::IllegalArgumentException(
|
||||
"Phone numbers and types lengths differ".to_owned(),
|
||||
));
|
||||
}
|
||||
if emails.len() != email_types.len() {
|
||||
return Err(Exceptions::IllegalArgumentException(
|
||||
"Emails and types lengths differ".to_owned(),
|
||||
));
|
||||
}
|
||||
if addresses.len() != address_types.len() {
|
||||
return Err(Exceptions::IllegalArgumentException(
|
||||
"Addresses and types lengths differ".to_owned(),
|
||||
));
|
||||
}
|
||||
Ok(Self {
|
||||
names,
|
||||
nicknames,
|
||||
pronunciation,
|
||||
phone_numbers,
|
||||
phone_types,
|
||||
emails,
|
||||
email_types,
|
||||
instant_messenger,
|
||||
note,
|
||||
addresses,
|
||||
address_types,
|
||||
org,
|
||||
birthday,
|
||||
title,
|
||||
urls,
|
||||
geo,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn getNames(&self) -> &Vec<String> {
|
||||
&self.names
|
||||
}
|
||||
|
||||
pub fn getNicknames(&self) -> &Vec<String> {
|
||||
&self.nicknames
|
||||
}
|
||||
|
||||
/**
|
||||
* In Japanese, the name is written in kanji, which can have multiple readings. Therefore a hint
|
||||
* is often provided, called furigana, which spells the name phonetically.
|
||||
*
|
||||
* @return The pronunciation of the getNames() field, often in hiragana or katakana.
|
||||
*/
|
||||
pub fn getPronunciation(&self) -> &str {
|
||||
&self.pronunciation
|
||||
}
|
||||
|
||||
pub fn getPhoneNumbers(&self) -> &Vec<String> {
|
||||
&self.phone_numbers
|
||||
}
|
||||
|
||||
/**
|
||||
* @return optional descriptions of the type of each phone number. It could be like "HOME", but,
|
||||
* there is no guaranteed or standard format.
|
||||
*/
|
||||
pub fn getPhoneTypes(&self) -> &Vec<String> {
|
||||
&self.phone_types
|
||||
}
|
||||
|
||||
pub fn getEmails(&self) -> &Vec<String> {
|
||||
&self.emails
|
||||
}
|
||||
|
||||
/**
|
||||
* @return optional descriptions of the type of each e-mail. It could be like "WORK", but,
|
||||
* there is no guaranteed or standard format.
|
||||
*/
|
||||
pub fn getEmailTypes(&self) -> &Vec<String> {
|
||||
&self.email_types
|
||||
}
|
||||
|
||||
pub fn getInstantMessenger(&self) -> &str {
|
||||
&self.instant_messenger
|
||||
}
|
||||
|
||||
pub fn getNote(&self) -> &str {
|
||||
&self.note
|
||||
}
|
||||
|
||||
pub fn getAddresses(&self) -> &Vec<String> {
|
||||
&self.addresses
|
||||
}
|
||||
|
||||
/**
|
||||
* @return optional descriptions of the type of each e-mail. It could be like "WORK", but,
|
||||
* there is no guaranteed or standard format.
|
||||
*/
|
||||
pub fn getAddressTypes(&self) -> &Vec<String> {
|
||||
&self.address_types
|
||||
}
|
||||
|
||||
pub fn getTitle(&self) -> &str {
|
||||
&self.title
|
||||
}
|
||||
|
||||
pub fn getOrg(&self) -> &str {
|
||||
&self.org
|
||||
}
|
||||
|
||||
pub fn getURLs(&self) -> &Vec<String> {
|
||||
&self.urls
|
||||
}
|
||||
|
||||
/**
|
||||
* @return birthday formatted as yyyyMMdd (e.g. 19780917)
|
||||
*/
|
||||
pub fn getBirthday(&self) -> &str {
|
||||
&self.birthday
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a location as a latitude/longitude pair
|
||||
*/
|
||||
pub fn getGeo(&self) -> &Vec<String> {
|
||||
&self.geo
|
||||
}
|
||||
}
|
||||
@@ -1,169 +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 AddressBookParsedRXingResult}.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class AddressBookParsedRXingResultTestCase extends Assert {
|
||||
|
||||
@Test
|
||||
public void testAddressBookDocomo() {
|
||||
doTest("MECARD:N:Sean Owen;;", null, new String[] {"Sean Owen"},
|
||||
null, null, null, null, null, null, null, null, null);
|
||||
doTest("MECARD:NOTE:ZXing Team;N:Sean Owen;URL:google.com;EMAIL:srowen@example.org;;",
|
||||
null, new String[] {"Sean Owen"}, null, null, new String[] {"srowen@example.org"}, null, null, null,
|
||||
new String[] {"google.com"}, null, "ZXing Team");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddressBookAU() {
|
||||
doTest("MEMORY:foo\r\nNAME1:Sean\r\nTEL1:+12125551212\r\n",
|
||||
null, new String[] {"Sean"}, null, null, null, new String[] {"+12125551212"}, null, null, null, null, "foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVCard() {
|
||||
doTest("BEGIN:VCARD\r\nADR;HOME:123 Main St\r\nVERSION:2.1\r\nN:Owen;Sean\r\nEND:VCARD",
|
||||
null, new String[] {"Sean Owen"}, null, new String[] {"123 Main St"},
|
||||
null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVCardFullN() {
|
||||
doTest("BEGIN:VCARD\r\nVERSION:2.1\r\nN:Owen;Sean;T;Mr.;Esq.\r\nEND:VCARD",
|
||||
null, new String[] {"Mr. Sean T Owen Esq."}, null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVCardFullN2() {
|
||||
doTest("BEGIN:VCARD\r\nVERSION:2.1\r\nN:Owen;Sean;;;\r\nEND:VCARD",
|
||||
null, new String[] {"Sean Owen"}, null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVCardFullN3() {
|
||||
doTest("BEGIN:VCARD\r\nVERSION:2.1\r\nN:;Sean;;;\r\nEND:VCARD",
|
||||
null, new String[] {"Sean"}, null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVCardCaseInsensitive() {
|
||||
doTest("begin:vcard\r\nadr;HOME:123 Main St\r\nVersion:2.1\r\nn:Owen;Sean\r\nEND:VCARD",
|
||||
null, new String[] {"Sean Owen"}, null, new String[] {"123 Main St"},
|
||||
null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEscapedVCard() {
|
||||
doTest("BEGIN:VCARD\r\nADR;HOME:123\\;\\\\ Main\\, St\\nHome\r\nVERSION:2.1\r\nN:Owen;Sean\r\nEND:VCARD",
|
||||
null, new String[] {"Sean Owen"}, null, new String[] {"123;\\ Main, St\nHome"},
|
||||
null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBizcard() {
|
||||
doTest("BIZCARD:N:Sean;X:Owen;C:Google;A:123 Main St;M:+12125551212;E:srowen@example.org;",
|
||||
null, new String[] {"Sean Owen"}, null, new String[] {"123 Main St"}, new String[] {"srowen@example.org"},
|
||||
new String[] {"+12125551212"}, null, "Google", null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSeveralAddresses() {
|
||||
doTest("MECARD:N:Foo Bar;ORG:Company;TEL:5555555555;EMAIL:foo.bar@xyz.com;ADR:City, 10001;" +
|
||||
"ADR:City, 10001;NOTE:This is the memo.;;",
|
||||
null, new String[] {"Foo Bar"}, null, new String[] {"City, 10001", "City, 10001"},
|
||||
new String[] {"foo.bar@xyz.com"},
|
||||
new String[] {"5555555555" }, null, "Company", null, null, "This is the memo.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuotedPrintable() {
|
||||
doTest("BEGIN:VCARD\r\nADR;HOME;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:;;" +
|
||||
"=38=38=20=4C=79=6E=62=72=6F=6F=6B=0D=0A=43=\r\n" +
|
||||
"=4F=20=36=39=39=\r\n" +
|
||||
"=39=39;;;\r\nEND:VCARD",
|
||||
null, null, null, new String[] {"88 Lynbrook\r\nCO 69999"},
|
||||
null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVCardEscape() {
|
||||
doTest("BEGIN:VCARD\r\nNOTE:foo\\nbar\r\nEND:VCARD",
|
||||
null, null, null, null, null, null, null, null, null, null, "foo\nbar");
|
||||
doTest("BEGIN:VCARD\r\nNOTE:foo\\;bar\r\nEND:VCARD",
|
||||
null, null, null, null, null, null, null, null, null, null, "foo;bar");
|
||||
doTest("BEGIN:VCARD\r\nNOTE:foo\\\\bar\r\nEND:VCARD",
|
||||
null, null, null, null, null, null, null, null, null, null, "foo\\bar");
|
||||
doTest("BEGIN:VCARD\r\nNOTE:foo\\,bar\r\nEND:VCARD",
|
||||
null, null, null, null, null, null, null, null, null, null, "foo,bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVCardValueURI() {
|
||||
doTest("BEGIN:VCARD\r\nTEL;VALUE=uri:tel:+1-555-555-1212\r\nEND:VCARD",
|
||||
null, null, null, null, null, new String[] { "+1-555-555-1212" }, new String[] { null },
|
||||
null, null, null, null);
|
||||
|
||||
doTest("BEGIN:VCARD\r\nN;VALUE=text:Owen;Sean\r\nEND:VCARD",
|
||||
null, new String[] {"Sean Owen"}, null, null, null, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVCardTypes() {
|
||||
doTest("BEGIN:VCARD\r\nTEL;HOME:\r\nTEL;WORK:10\r\nTEL:20\r\nTEL;CELL:30\r\nEND:VCARD",
|
||||
null, null, null, null, null, new String[] { "10", "20", "30" },
|
||||
new String[] { "WORK", null, "CELL" }, null, null, null, null);
|
||||
}
|
||||
|
||||
private static void doTest(String contents,
|
||||
String title,
|
||||
String[] names,
|
||||
String pronunciation,
|
||||
String[] addresses,
|
||||
String[] emails,
|
||||
String[] phoneNumbers,
|
||||
String[] phoneTypes,
|
||||
String org,
|
||||
String[] urls,
|
||||
String birthday,
|
||||
String note) {
|
||||
RXingResult fakeRXingResult = new RXingResult(contents, null, null, BarcodeFormat.QR_CODE);
|
||||
ParsedRXingResult result = RXingResultParser.parseRXingResult(fakeRXingResult);
|
||||
assertSame(ParsedRXingResultType.ADDRESSBOOK, result.getType());
|
||||
AddressBookParsedRXingResult addressRXingResult = (AddressBookParsedRXingResult) result;
|
||||
assertEquals(title, addressRXingResult.getTitle());
|
||||
assertArrayEquals(names, addressRXingResult.getNames());
|
||||
assertEquals(pronunciation, addressRXingResult.getPronunciation());
|
||||
assertArrayEquals(addresses, addressRXingResult.getAddresses());
|
||||
assertArrayEquals(emails, addressRXingResult.getEmails());
|
||||
assertArrayEquals(phoneNumbers, addressRXingResult.getPhoneNumbers());
|
||||
assertArrayEquals(phoneTypes, addressRXingResult.getPhoneTypes());
|
||||
assertEquals(org, addressRXingResult.getOrg());
|
||||
assertArrayEquals(urls, addressRXingResult.getURLs());
|
||||
assertEquals(birthday, addressRXingResult.getBirthday());
|
||||
assertEquals(note, addressRXingResult.getNote());
|
||||
}
|
||||
|
||||
}
|
||||
372
src/client/result/AddressBookParsedResultTestCase.rs
Normal file
372
src/client/result/AddressBookParsedResultTestCase.rs
Normal file
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* 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 AddressBookParsedRXingResult}.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
// public final class AddressBookParsedRXingResultTestCase extends Assert {
|
||||
use crate::{
|
||||
client::result::{ParsedClientResult, ParsedRXingResult, ParsedRXingResultType, ResultParser},
|
||||
BarcodeFormat, RXingResult,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn testAddressBookDocomo() {
|
||||
doTest(
|
||||
"MECARD:N:Sean Owen;;",
|
||||
"",
|
||||
&vec!["Sean Owen"],
|
||||
"",
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"",
|
||||
);
|
||||
doTest(
|
||||
"MECARD:NOTE:ZXing Team;N:Sean Owen;URL:google.com;EMAIL:srowen@example.org;;",
|
||||
"",
|
||||
&vec!["Sean Owen"],
|
||||
"",
|
||||
&Vec::new(),
|
||||
&vec!["srowen@example.org"],
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
"",
|
||||
&vec!["google.com"],
|
||||
"",
|
||||
"ZXing Team",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testAddressBookAU() {
|
||||
doTest(
|
||||
"MEMORY:foo\r\nNAME1:Sean\r\nTEL1:+12125551212\r\n",
|
||||
"",
|
||||
&vec!["Sean"],
|
||||
"",
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&vec!["+12125551212"],
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"foo",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testVCard() {
|
||||
doTest(
|
||||
"BEGIN:VCARD\r\nADR;HOME:123 Main St\r\nVERSION:2.1\r\nN:Owen;Sean\r\nEND:VCARD",
|
||||
"",
|
||||
&vec!["Sean Owen"],
|
||||
"",
|
||||
&vec!["123 Main St"],
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testVCardFullN() {
|
||||
doTest(
|
||||
"BEGIN:VCARD\r\nVERSION:2.1\r\nN:Owen;Sean;T;Mr.;Esq.\r\nEND:VCARD",
|
||||
"",
|
||||
&vec!["Mr. Sean T Owen Esq."],
|
||||
"",
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testVCardFullN2() {
|
||||
doTest(
|
||||
"BEGIN:VCARD\r\nVERSION:2.1\r\nN:Owen;Sean;;;\r\nEND:VCARD",
|
||||
"",
|
||||
&vec!["Sean Owen"],
|
||||
"",
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testVCardFullN3() {
|
||||
doTest(
|
||||
"BEGIN:VCARD\r\nVERSION:2.1\r\nN:;Sean;;;\r\nEND:VCARD",
|
||||
"",
|
||||
&vec!["Sean"],
|
||||
"",
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testVCardCaseInsensitive() {
|
||||
doTest(
|
||||
"begin:vcard\r\nadr;HOME:123 Main St\r\nVersion:2.1\r\nn:Owen;Sean\r\nEND:VCARD",
|
||||
"",
|
||||
&vec!["Sean Owen"],
|
||||
"",
|
||||
&vec!["123 Main St"],
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testEscapedVCard() {
|
||||
doTest("BEGIN:VCARD\r\nADR;HOME:123\\;\\\\ Main\\, St\\nHome\r\nVERSION:2.1\r\nN:Owen;Sean\r\nEND:VCARD",
|
||||
"", &vec!["Sean Owen"], "", &vec!["123;\\ Main, St\nHome"],
|
||||
&Vec::new(), &Vec::new(), &Vec::new(), "", &Vec::new(), "", "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testBizcard() {
|
||||
doTest(
|
||||
"BIZCARD:N:Sean;X:Owen;C:Google;A:123 Main St;M:+12125551212;E:srowen@example.org;",
|
||||
"",
|
||||
&vec!["Sean Owen"],
|
||||
"",
|
||||
&vec!["123 Main St"],
|
||||
&vec!["srowen@example.org"],
|
||||
&vec!["+12125551212"],
|
||||
&Vec::new(),
|
||||
"Google",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testSeveralAddresses() {
|
||||
doTest("MECARD:N:Foo Bar;ORG:Company;TEL:5555555555;EMAIL:foo.bar@xyz.com;ADR:City, 10001;ADR:City, 10001;NOTE:This is the memo.;;",
|
||||
"", &vec!["Foo Bar"], "", &vec!["City, 10001", "City, 10001"],
|
||||
&vec!["foo.bar@xyz.com"],
|
||||
&vec!["5555555555" ], &Vec::new(), "Company", &Vec::new(), "", "This is the memo.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testQuotedPrintable() {
|
||||
doTest(
|
||||
"BEGIN:VCARD\r\nADR;HOME;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:;;=38=38=20=4C=79=6E=62=72=6F=6F=6B=0D=0A=43=\r\n=4F=20=36=39=39=\r\n=39=39;;;\r\nEND:VCARD",
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
&vec!["88 Lynbrook\r\nCO 69999"],
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testVCardEscape() {
|
||||
doTest(
|
||||
"BEGIN:VCARD\r\nNOTE:foo\\nbar\r\nEND:VCARD",
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"foo\nbar",
|
||||
);
|
||||
doTest(
|
||||
"BEGIN:VCARD\r\nNOTE:foo\\;bar\r\nEND:VCARD",
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"foo;bar",
|
||||
);
|
||||
doTest(
|
||||
"BEGIN:VCARD\r\nNOTE:foo\\\\bar\r\nEND:VCARD",
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"foo\\bar",
|
||||
);
|
||||
doTest(
|
||||
"BEGIN:VCARD\r\nNOTE:foo\\,bar\r\nEND:VCARD",
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"foo,bar",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testVCardValueURI() {
|
||||
doTest(
|
||||
"BEGIN:VCARD\r\nTEL;VALUE=uri:tel:+1-555-555-1212\r\nEND:VCARD",
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&vec!["+1-555-555-1212"],
|
||||
&vec![""],
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"",
|
||||
);
|
||||
|
||||
doTest(
|
||||
"BEGIN:VCARD\r\nN;VALUE=text:Owen;Sean\r\nEND:VCARD",
|
||||
"",
|
||||
&vec!["Sean Owen"],
|
||||
"",
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn testVCardTypes() {
|
||||
doTest(
|
||||
"BEGIN:VCARD\r\nTEL;HOME:\r\nTEL;WORK:10\r\nTEL:20\r\nTEL;CELL:30\r\nEND:VCARD",
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
&Vec::new(),
|
||||
&Vec::new(),
|
||||
&vec!["10", "20", "30"],
|
||||
&vec!["WORK", "", "CELL"],
|
||||
"",
|
||||
&Vec::new(),
|
||||
"",
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
fn doTest(
|
||||
contents: &str,
|
||||
title: &str,
|
||||
names: &[&str],
|
||||
pronunciation: &str,
|
||||
addresses: &[&str],
|
||||
emails: &[&str],
|
||||
phoneNumbers: &[&str],
|
||||
phoneTypes: &[&str],
|
||||
org: &str,
|
||||
urls: &[&str],
|
||||
birthday: &str,
|
||||
note: &str,
|
||||
) {
|
||||
let fakeRXingResult =
|
||||
RXingResult::new(contents, Vec::new(), Vec::new(), BarcodeFormat::QR_CODE);
|
||||
let result = ResultParser::parseRXingResult(&fakeRXingResult);
|
||||
assert_eq!(ParsedRXingResultType::ADDRESSBOOK, result.getType());
|
||||
if let ParsedClientResult::AddressBookResult(addressRXingResult) = result {
|
||||
assert_eq!(title, addressRXingResult.getTitle());
|
||||
assert_eq!(names, addressRXingResult.getNames());
|
||||
assert_eq!(pronunciation, addressRXingResult.getPronunciation());
|
||||
assert_eq!(addresses, addressRXingResult.getAddresses());
|
||||
assert_eq!(emails, addressRXingResult.getEmails());
|
||||
assert_eq!(phoneNumbers, addressRXingResult.getPhoneNumbers());
|
||||
assert_eq!(phoneTypes, addressRXingResult.getPhoneTypes());
|
||||
assert_eq!(org, addressRXingResult.getOrg());
|
||||
assert_eq!(urls, addressRXingResult.getURLs());
|
||||
assert_eq!(birthday, addressRXingResult.getBirthday());
|
||||
assert_eq!(note, addressRXingResult.getNote());
|
||||
} else {
|
||||
panic!("Expected address book result");
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
@@ -164,7 +164,7 @@ pub fn maybe_append_multiple(value: &[String], result: &mut String) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maybeWrap(value: Option<&str>) -> Option<Vec<String>> {
|
||||
pub fn maybeWrap(value: Option<String>) -> Option<Vec<String>> {
|
||||
if value.is_none() {
|
||||
None
|
||||
} else {
|
||||
|
||||
@@ -14,45 +14,46 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.zxing.client.result;
|
||||
// package com.google.zxing.client.result;
|
||||
|
||||
import com.google.zxing.RXingResult;
|
||||
// import com.google.zxing.RXingResult;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
// import java.io.ByteArrayOutputStream;
|
||||
// import java.io.UnsupportedEncodingException;
|
||||
// import java.net.URI;
|
||||
// import java.nio.charset.StandardCharsets;
|
||||
// import java.util.ArrayList;
|
||||
// import java.util.Collection;
|
||||
// import java.util.List;
|
||||
// import java.util.regex.Matcher;
|
||||
// import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
use crate::RXingResult;
|
||||
|
||||
use super::ParsedClientResult;
|
||||
|
||||
const BEGIN_VCARD : &'static str = "BEGIN:VCARD";//, Pattern.CASE_INSENSITIVE);
|
||||
const VCARD_LIKE_DATE : &'static str = "\\d{4}-?\\d{2}-?\\d{2}";
|
||||
const CR_LF_SPACE_TAB : &'static str = "\r\n[ \t]";
|
||||
const NEWLINE_ESCAPE : &'static str = "\\\\[nN]";
|
||||
const VCARD_ESCAPES : &'static str = "\\\\([,;\\\\])";
|
||||
const EQUALS : &'static str = "=";
|
||||
const SEMICOLON : &'static str = ";";
|
||||
const UNESCAPED_SEMICOLONS : &'static str = "(?<!\\\\);+";
|
||||
const COMMA : &'static str = ",";
|
||||
const SEMICOLON_OR_COMMA : &'static str = "[;,]";
|
||||
|
||||
/**
|
||||
* Parses contact information formatted according to the VCard (2.1) format. This is not a complete
|
||||
* implementation but should parse information as commonly encoded in 2D barcodes.
|
||||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
public final class VCardRXingResultParser extends RXingResultParser {
|
||||
|
||||
private static final Pattern BEGIN_VCARD = Pattern.compile("BEGIN:VCARD", Pattern.CASE_INSENSITIVE);
|
||||
private static final Pattern VCARD_LIKE_DATE = Pattern.compile("\\d{4}-?\\d{2}-?\\d{2}");
|
||||
private static final Pattern CR_LF_SPACE_TAB = Pattern.compile("\r\n[ \t]");
|
||||
private static final Pattern NEWLINE_ESCAPE = Pattern.compile("\\\\[nN]");
|
||||
private static final Pattern VCARD_ESCAPES = Pattern.compile("\\\\([,;\\\\])");
|
||||
private static final Pattern EQUALS = Pattern.compile("=");
|
||||
private static final Pattern SEMICOLON = Pattern.compile(";");
|
||||
private static final Pattern UNESCAPED_SEMICOLONS = Pattern.compile("(?<!\\\\);+");
|
||||
private static final Pattern COMMA = Pattern.compile(",");
|
||||
private static final Pattern SEMICOLON_OR_COMMA = Pattern.compile("[;,]");
|
||||
|
||||
@Override
|
||||
public AddressBookParsedRXingResult parse(RXingResult result) {
|
||||
pub fn parse(result: &RXingResult) -> Option<ParsedClientResult> {
|
||||
// Although we should insist on the raw text ending with "END:VCARD", there's no reason
|
||||
// to throw out everything else we parsed just because this was omitted. In fact, Eclair
|
||||
// is doing just that, and we can't parse its contacts without this leniency.
|
||||
String rawText = getMassagedText(result);
|
||||
let rawText = getMassagedText(result);
|
||||
Matcher m = BEGIN_VCARD.matcher(rawText);
|
||||
if (!m.find() || m.start() != 0) {
|
||||
return null;
|
||||
@@ -100,10 +101,10 @@ public final class VCardRXingResultParser extends RXingResultParser {
|
||||
geo);
|
||||
}
|
||||
|
||||
static List<List<String>> matchVCardPrefixedField(CharSequence prefix,
|
||||
String rawText,
|
||||
boolean trim,
|
||||
boolean parseFieldDivider) {
|
||||
fn matchVCardPrefixedField( prefix:&str,
|
||||
rawText:&str,
|
||||
trim:bool,
|
||||
parseFieldDivider:bool) -> Vec<String> {
|
||||
List<List<String>> matches = null;
|
||||
int i = 0;
|
||||
int max = rawText.length();
|
||||
@@ -220,7 +221,7 @@ public final class VCardRXingResultParser extends RXingResultParser {
|
||||
return matches;
|
||||
}
|
||||
|
||||
private static String decodeQuotedPrintable(CharSequence value, String charset) {
|
||||
fn decodeQuotedPrintable( value:&str, charset:&str) -> String{
|
||||
int length = value.length();
|
||||
StringBuilder result = new StringBuilder(length);
|
||||
ByteArrayOutputStream fragmentBuffer = new ByteArrayOutputStream();
|
||||
@@ -253,9 +254,9 @@ public final class VCardRXingResultParser extends RXingResultParser {
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static void maybeAppendFragment(ByteArrayOutputStream fragmentBuffer,
|
||||
String charset,
|
||||
StringBuilder result) {
|
||||
fn maybeAppendFragment( fragmentBuffer &Vec<u8>,
|
||||
charset:&str,
|
||||
result:&mut String) {
|
||||
if (fragmentBuffer.size() > 0) {
|
||||
byte[] fragmentBytes = fragmentBuffer.toByteArray();
|
||||
String fragment;
|
||||
@@ -273,19 +274,19 @@ public final class VCardRXingResultParser extends RXingResultParser {
|
||||
}
|
||||
}
|
||||
|
||||
static List<String> matchSingleVCardPrefixedField(CharSequence prefix,
|
||||
String rawText,
|
||||
boolean trim,
|
||||
boolean parseFieldDivider) {
|
||||
fn matchSingleVCardPrefixedField( prefix:&str,
|
||||
rawText:&str,
|
||||
trim :bool,
|
||||
parseFieldDivider:bool)->Vec<String> {
|
||||
List<List<String>> values = matchVCardPrefixedField(prefix, rawText, trim, parseFieldDivider);
|
||||
return values == null || values.isEmpty() ? null : values.get(0);
|
||||
}
|
||||
|
||||
private static String toPrimaryValue(List<String> list) {
|
||||
fn toPrimaryValue(list:&Vec<String>) -> String{
|
||||
return list == null || list.isEmpty() ? null : list.get(0);
|
||||
}
|
||||
|
||||
private static String[] toPrimaryValues(Collection<List<String>> lists) {
|
||||
fn toPrimaryValues( lists:&Vec<String>) -> Vec<String>{
|
||||
if (lists == null || lists.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -299,7 +300,7 @@ public final class VCardRXingResultParser extends RXingResultParser {
|
||||
return result.toArray(EMPTY_STR_ARRAY);
|
||||
}
|
||||
|
||||
private static String[] toTypes(Collection<List<String>> lists) {
|
||||
fn toTypes( lists: &Vec<String>) -> Vec<String>{
|
||||
if (lists == null || lists.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -327,7 +328,7 @@ public final class VCardRXingResultParser extends RXingResultParser {
|
||||
return result.toArray(EMPTY_STR_ARRAY);
|
||||
}
|
||||
|
||||
private static boolean isLikeVCardDate(CharSequence value) {
|
||||
fn isLikeVCardDate( value:&str) -> bool{
|
||||
return value == null || VCARD_LIKE_DATE.matcher(value).matches();
|
||||
}
|
||||
|
||||
@@ -337,21 +338,22 @@ public final class VCardRXingResultParser extends RXingResultParser {
|
||||
*
|
||||
* @param names name values to format, in place
|
||||
*/
|
||||
private static void formatNames(Iterable<List<String>> names) {
|
||||
if (names != null) {
|
||||
for (List<String> list : names) {
|
||||
String name = list.get(0);
|
||||
String[] components = new String[5];
|
||||
int start = 0;
|
||||
int end;
|
||||
int componentIndex = 0;
|
||||
while (componentIndex < components.length - 1 && (end = name.indexOf(';', start)) >= 0) {
|
||||
fn formatNames( names : &mut Vec<String>) {
|
||||
if !names.is_empty() {
|
||||
for list in names {
|
||||
// for (List<String> list : names) {
|
||||
let name = list.get(0);
|
||||
let components = vec!["";5];
|
||||
let start = 0;
|
||||
let end;
|
||||
let componentIndex = 0;
|
||||
while componentIndex < components.len() - 1 && (end = name.indexOf(';', start)) >= 0 {
|
||||
components[componentIndex] = name.substring(start, end);
|
||||
componentIndex++;
|
||||
componentIndex+=1;
|
||||
start = end + 1;
|
||||
}
|
||||
components[componentIndex] = name.substring(start);
|
||||
StringBuilder newName = new StringBuilder(100);
|
||||
let newName = String::with_capacity(100);
|
||||
maybeAppendComponent(components, 3, newName);
|
||||
maybeAppendComponent(components, 1, newName);
|
||||
maybeAppendComponent(components, 2, newName);
|
||||
@@ -362,13 +364,11 @@ public final class VCardRXingResultParser extends RXingResultParser {
|
||||
}
|
||||
}
|
||||
|
||||
private static void maybeAppendComponent(String[] components, int i, StringBuilder newName) {
|
||||
if (components[i] != null && !components[i].isEmpty()) {
|
||||
if (newName.length() > 0) {
|
||||
newName.append(' ');
|
||||
fn maybeAppendComponent( components : &Vec<String>, i:usize, newName:&mut String) {
|
||||
if !components[i].is_empty() {
|
||||
if newName.len() > 0 {
|
||||
newName.push(' ');
|
||||
}
|
||||
newName.append(components[i]);
|
||||
newName.push_str(&components[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,11 @@ mod EmailDoCoMoResultParser;
|
||||
mod SMTPResultParser;
|
||||
mod VINParsedResult;
|
||||
mod VINResultParser;
|
||||
mod AddressBookParsedResult;
|
||||
mod AddressBookDoCoMoResultParser;
|
||||
mod AddressBookAUResultParser;
|
||||
mod VCardResultParser;
|
||||
mod AddressBookParsedResultTestCase;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
@@ -46,6 +51,7 @@ pub use ProductParsedResult::*;
|
||||
pub use URIParsedResult::*;
|
||||
pub use EmailAddressParsedResult::*;
|
||||
pub use VINParsedResult::*;
|
||||
pub use AddressBookParsedResult::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod TelParsedResultTestCase;
|
||||
@@ -77,6 +83,7 @@ pub enum ParsedClientResult {
|
||||
URIResult(URIParsedRXingResult),
|
||||
EmailResult(EmailAddressParsedRXingResult),
|
||||
VINResult(VINParsedRXingResult),
|
||||
AddressBookResult(AddressBookParsedRXingResult),
|
||||
}
|
||||
|
||||
impl ParsedRXingResult for ParsedClientResult {
|
||||
@@ -92,6 +99,7 @@ impl ParsedRXingResult for ParsedClientResult {
|
||||
ParsedClientResult::URIResult(a) => a.getType(),
|
||||
ParsedClientResult::EmailResult(a) => a.getType(),
|
||||
ParsedClientResult::VINResult(a) => a.getType(),
|
||||
ParsedClientResult::AddressBookResult(a) => a.getType(),
|
||||
|
||||
|
||||
}
|
||||
@@ -109,6 +117,7 @@ impl ParsedRXingResult for ParsedClientResult {
|
||||
ParsedClientResult::URIResult(a) => a.getDisplayRXingResult(),
|
||||
ParsedClientResult::EmailResult(a) => a.getDisplayRXingResult(),
|
||||
ParsedClientResult::VINResult(a) => a.getDisplayRXingResult(),
|
||||
ParsedClientResult::AddressBookResult(a) => a.getDisplayRXingResult(),
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user