Skip to content

Commit

Permalink
can now get it when street parts are an array of strings
Browse files Browse the repository at this point in the history
  • Loading branch information
anewton1998 committed Sep 5, 2024
1 parent 9d2820f commit 565a4e0
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 26 deletions.
162 changes: 137 additions & 25 deletions icann-rdap-common/src/contact/from_vcard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,33 +326,84 @@ impl<'a> GetPostalAddresses<'a> for &'a [&'a Vec<Value>] {
let mut street_parts: Vec<String> = Vec::new();
if let Some(fourth) = prop.get(3) {
if let Some(addr) = fourth.as_array() {
let mut iter = addr
.iter()
.rev()
.filter_map(|i| i.as_str())
.filter(|i| !i.is_empty());
if let Some(e) = iter.next() {
if e.len() == 2 && e.to_uppercase() == e {
country_code = Some(e.to_string())
} else {
country_name = Some(e.to_string())
// the jcard address fields are in a different index of the array.
//
// [
// "adr",
// {},
// "text",
// [
// "Mail Stop 3", // post office box (not recommended for use)
// "Suite 3000", // apartment or suite (not recommended for use)
// "123 Maple Ave", // street address
// "Quebec", // locality or city name
// "QC", // region (can be either a code or full name)
// "G1V 2M2", // postal code
// "Canada" // full country name
// ]
// ],
if let Some(pobox) = addr.first() {
if let Some(s) = pobox.as_str() {
if !s.is_empty() {
street_parts.push(s.to_string())
}
}
};
if let Some(e) = iter.next() {
postal_code = Some(e.to_string());
};
if let Some(e) = iter.next() {
if e.len() == 2 && e.to_uppercase() == e {
region_code = Some(e.to_string())
} else {
region_name = Some(e.to_string())
}
if let Some(appt) = addr.get(1) {
if let Some(s) = appt.as_str() {
if !s.is_empty() {
street_parts.push(s.to_string())
}
}
}
if let Some(street) = addr.get(2) {
if let Some(s) = street.as_str() {
if !s.is_empty() {
street_parts.push(s.to_string())
}
} else if let Some(arry_s) = street.as_array() {
arry_s
.iter()
.filter_map(|v| v.as_str())
.filter(|s| !s.is_empty())
.for_each(|s| street_parts.push(s.to_string()))
}
}
if let Some(city) = addr.get(3) {
if let Some(s) = city.as_str() {
if !s.is_empty() {
locality = Some(s.to_string());
}
}
}
if let Some(region) = addr.get(4) {
if let Some(s) = region.as_str() {
if !s.is_empty() {
if s.len() == 2 && s.to_uppercase() == s {
region_code = Some(s.to_string())
} else {
region_name = Some(s.to_string())
}
}
}
}
if let Some(pc) = addr.get(5) {
if let Some(s) = pc.as_str() {
if !s.is_empty() {
postal_code = Some(s.to_string());
}
}
}
if let Some(country) = addr.get(6) {
if let Some(s) = country.as_str() {
if !s.is_empty() {
if s.len() == 2 && s.to_uppercase() == s {
country_code = Some(s.to_string())
} else {
country_name = Some(s.to_string())
}
}
}
};
if let Some(e) = iter.next() {
locality = Some(e.to_string());
};
for e in iter {
street_parts.insert(0, e.to_string());
}
}
};
Expand Down Expand Up @@ -711,4 +762,65 @@ mod tests {
"https://example.com/some-url"
);
}

#[test]
fn GIVEN_vcard_with_addr_street_array_WHEN_from_vcard_THEN_properties_are_correct() {
// GIVEN
let vcard = r#"
[
"vcard",
[
["version", {}, "text", "4.0"],
["fn", {}, "text", "Joe User"],
["adr",
{ "type":"work" },
"text",
[
"",
"Suite 1234",
["4321 Rue Blue", "1, Gawwn"],
"Quebec",
"QC",
"G1V 2M2",
"Canada"
]
]
]
]
"#;

// WHEN
let actual = serde_json::from_str::<Vec<Value>>(vcard);

// THEN
let actual = actual.expect("parsing vcard");
let actual = Contact::from_vcard(&actual).expect("vcard not found");

// full name
assert_eq!(actual.full_name.expect("full_name not found"), "Joe User");

// postal addresses
let Some(addresses) = actual.postal_addresses else {
panic!("no postal addresses")
};
let Some(addr) = addresses.first() else {
panic!("first address not found")
};
assert!(addr
.contexts
.as_ref()
.expect("no contexts")
.contains(&"work".to_string()));
let Some(street_parts) = &addr.street_parts else {
panic!("no street parts")
};
assert_eq!(street_parts.first().expect("street part 0"), "Suite 1234");
assert_eq!(street_parts.get(1).expect("street part 1"), "4321 Rue Blue");
assert_eq!(street_parts.get(2).expect("street part 2"), "1, Gawwn");
assert_eq!(addr.country_name.as_ref().expect("country name"), "Canada");
assert!(addr.country_code.is_none());
assert_eq!(addr.region_code.as_ref().expect("region code"), "QC");
assert!(addr.region_name.is_none());
assert_eq!(addr.postal_code.as_ref().expect("postal code"), "G1V 2M2");
}
}
12 changes: 11 additions & 1 deletion icann-rdap-common/src/contact/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,17 @@ pub struct PostalAddress {
/// Work, home, etc.... Known as "type" in JCard.
pub contexts: Option<Vec<String>>,

/// An unstructured address.
/// An unstructured address. An unstructured postal address is
/// usually the complete postal address. That is, this string
/// would contain the street address, country, region, postal code, etc...
///
/// Depending on how the postal address is given, it can either
/// be structured or unstructured. If it is given as unstructured,
/// then this value is populated.
///
/// It is possible that a single postal address is given as both,
/// in which case this value is populated along with the other
/// values of the postal address.
pub full_address: Option<String>,

/// Invidual street lines.
Expand Down

0 comments on commit 565a4e0

Please sign in to comment.