From 582dd75c02b028f8a706cd0c1d8c6f49aee57590 Mon Sep 17 00:00:00 2001 From: Henry Schimke Date: Sat, 10 Sep 2022 14:55:32 -0500 Subject: [PATCH] still working through addresses --- .../result/AddressBookAUResultParser.java | 89 ----- .../result/AddressBookAUResultParser.rs | 99 +++++ .../result/AddressBookDoCoMoResultParser.java | 92 ----- .../result/AddressBookDoCoMoResultParser.rs | 111 ++++++ .../result/AddressBookParsedResult.java | 220 ----------- src/client/result/AddressBookParsedResult.rs | 242 ++++++++++++ .../AddressBookParsedResultTestCase.java | 169 -------- .../result/AddressBookParsedResultTestCase.rs | 372 ++++++++++++++++++ src/client/result/ResultParser.rs | 2 +- ...ResultParser.java => VCardResultParser.rs} | 124 +++--- src/client/result/mod.rs | 9 + 11 files changed, 896 insertions(+), 633 deletions(-) delete mode 100644 src/client/result/AddressBookAUResultParser.java create mode 100644 src/client/result/AddressBookAUResultParser.rs delete mode 100644 src/client/result/AddressBookDoCoMoResultParser.java create mode 100644 src/client/result/AddressBookDoCoMoResultParser.rs delete mode 100644 src/client/result/AddressBookParsedResult.java create mode 100644 src/client/result/AddressBookParsedResult.rs delete mode 100644 src/client/result/AddressBookParsedResultTestCase.java create mode 100644 src/client/result/AddressBookParsedResultTestCase.rs rename src/client/result/{VCardResultParser.java => VCardResultParser.rs} (78%) diff --git a/src/client/result/AddressBookAUResultParser.java b/src/client/result/AddressBookAUResultParser.java deleted file mode 100644 index 5edc94a..0000000 --- a/src/client/result/AddressBookAUResultParser.java +++ /dev/null @@ -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 - * - * http://www.au.kddi.com/ezfactory/tec/two_dimensions/index.html. - * (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 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); - } - -} diff --git a/src/client/result/AddressBookAUResultParser.rs b/src/client/result/AddressBookAUResultParser.rs new file mode 100644 index 0000000..651b7f0 --- /dev/null +++ b/src/client/result/AddressBookAUResultParser.rs @@ -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 + * + * http://www.au.kddi.com/ezfactory/tec/two_dimensions/index.html. + * (Thanks to Yuzo for translating!) + * + * @author Sean Owen + */ +pub fn parse(result: &RXingResult) -> Option { + 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 { + 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 +} diff --git a/src/client/result/AddressBookDoCoMoResultParser.java b/src/client/result/AddressBookDoCoMoResultParser.java deleted file mode 100644 index c44cfb4..0000000 --- a/src/client/result/AddressBookDoCoMoResultParser.java +++ /dev/null @@ -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; - } - -} diff --git a/src/client/result/AddressBookDoCoMoResultParser.rs b/src/client/result/AddressBookDoCoMoResultParser.rs new file mode 100644 index 0000000..c0e82c1 --- /dev/null +++ b/src/client/result/AddressBookDoCoMoResultParser.rs @@ -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 { + 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; +} + +// } diff --git a/src/client/result/AddressBookParsedResult.java b/src/client/result/AddressBookParsedResult.java deleted file mode 100644 index c1ea2ba..0000000 --- a/src/client/result/AddressBookParsedResult.java +++ /dev/null @@ -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(); - } - -} diff --git a/src/client/result/AddressBookParsedResult.rs b/src/client/result/AddressBookParsedResult.rs new file mode 100644 index 0000000..4f6563c --- /dev/null +++ b/src/client/result/AddressBookParsedResult.rs @@ -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, + nicknames: Vec, + pronunciation: String, + phone_numbers: Vec, + phone_types: Vec, + emails: Vec, + email_types: Vec, + instant_messenger: String, + note: String, + addresses: Vec, + address_types: Vec, + org: String, + birthday: String, + title: String, + urls: Vec, + geo: Vec, +} +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, + phone_numbers: Vec, + phone_types: Vec, + emails: Vec, + email_types: Vec, + addresses: Vec, + address_types: Vec, + ) -> Result { + 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, + nicknames: Vec, + pronunciation: String, + phone_numbers: Vec, + phone_types: Vec, + emails: Vec, + email_types: Vec, + instant_messenger: String, + note: String, + addresses: Vec, + address_types: Vec, + org: String, + birthday: String, + title: String, + urls: Vec, + geo: Vec, + ) -> Result { + 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 { + &self.names + } + + pub fn getNicknames(&self) -> &Vec { + &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 { + &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 { + &self.phone_types + } + + pub fn getEmails(&self) -> &Vec { + &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 { + &self.email_types + } + + pub fn getInstantMessenger(&self) -> &str { + &self.instant_messenger + } + + pub fn getNote(&self) -> &str { + &self.note + } + + pub fn getAddresses(&self) -> &Vec { + &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 { + &self.address_types + } + + pub fn getTitle(&self) -> &str { + &self.title + } + + pub fn getOrg(&self) -> &str { + &self.org + } + + pub fn getURLs(&self) -> &Vec { + &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 { + &self.geo + } +} diff --git a/src/client/result/AddressBookParsedResultTestCase.java b/src/client/result/AddressBookParsedResultTestCase.java deleted file mode 100644 index a2b734e..0000000 --- a/src/client/result/AddressBookParsedResultTestCase.java +++ /dev/null @@ -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()); - } - -} diff --git a/src/client/result/AddressBookParsedResultTestCase.rs b/src/client/result/AddressBookParsedResultTestCase.rs new file mode 100644 index 0000000..3453ae5 --- /dev/null +++ b/src/client/result/AddressBookParsedResultTestCase.rs @@ -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"); + } +} + +// } diff --git a/src/client/result/ResultParser.rs b/src/client/result/ResultParser.rs index c3f0e2f..8ae601a 100644 --- a/src/client/result/ResultParser.rs +++ b/src/client/result/ResultParser.rs @@ -164,7 +164,7 @@ pub fn maybe_append_multiple(value: &[String], result: &mut String) { } } -pub fn maybeWrap(value: Option<&str>) -> Option> { +pub fn maybeWrap(value: Option) -> Option> { if value.is_none() { None } else { diff --git a/src/client/result/VCardResultParser.java b/src/client/result/VCardResultParser.rs similarity index 78% rename from src/client/result/VCardResultParser.java rename to src/client/result/VCardResultParser.rs index 8a185bb..eb1bba3 100644 --- a/src/client/result/VCardResultParser.java +++ b/src/client/result/VCardResultParser.rs @@ -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 = "(? Option { // 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> matchVCardPrefixedField(CharSequence prefix, - String rawText, - boolean trim, - boolean parseFieldDivider) { + fn matchVCardPrefixedField( prefix:&str, + rawText:&str, + trim:bool, + parseFieldDivider:bool) -> Vec { List> 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, + 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 matchSingleVCardPrefixedField(CharSequence prefix, - String rawText, - boolean trim, - boolean parseFieldDivider) { + fn matchSingleVCardPrefixedField( prefix:&str, + rawText:&str, + trim :bool, + parseFieldDivider:bool)->Vec { List> values = matchVCardPrefixedField(prefix, rawText, trim, parseFieldDivider); return values == null || values.isEmpty() ? null : values.get(0); } - private static String toPrimaryValue(List list) { + fn toPrimaryValue(list:&Vec) -> String{ return list == null || list.isEmpty() ? null : list.get(0); } - private static String[] toPrimaryValues(Collection> lists) { + fn toPrimaryValues( lists:&Vec) -> Vec{ 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> lists) { + fn toTypes( lists: &Vec) -> Vec{ 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> names) { - if (names != null) { - for (List 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) { + if !names.is_empty() { + for list in names { + // for (List 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, 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]); } } - -} diff --git a/src/client/result/mod.rs b/src/client/result/mod.rs index 6ba74e7..665b4c5 100644 --- a/src/client/result/mod.rs +++ b/src/client/result/mod.rs @@ -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(),