Skip to content

Latest commit

 

History

History
235 lines (171 loc) · 6.43 KB

File metadata and controls

235 lines (171 loc) · 6.43 KB

contact module

Feature flag: contact

[dependencies]
arvo = { version = "1.0", features = ["contact"] }

EmailAddress

A validated, normalised email address.

Normalisation: trimmed, lowercased.
Validation: must match local@domain.tld pattern (RFC 5322 lite — full compliance intentionally out of scope).

use arvo::contact::EmailAddress;
use arvo::traits::{PrimitiveValue, ValueObject};

let email = EmailAddress::new("User@Example.COM".into())?;
assert_eq!(email.value(), "user@example.com");
assert_eq!(email.local_part(), "user");
assert_eq!(email.domain(), "example.com");

// try_into from &str
let email: EmailAddress = "hello@example.com".try_into()?;

Accessors

Method Returns Example
value() &String "user@example.com"
local_part() &str "user"
domain() &str "example.com"
into_inner() String "user@example.com"

Errors

Input Error
"" ValidationError::Empty
"notanemail" ValidationError::InvalidFormat

CountryCode

A validated ISO 3166-1 alpha-2 country code.

Normalisation: trimmed, uppercased.
Validation: exactly 2 ASCII letters.

use arvo::contact::CountryCode;
use arvo::traits::{PrimitiveValue, ValueObject};

let code = CountryCode::new("cz".into())?;
assert_eq!(code.value(), "CZ");

// try_into from &str
let code: CountryCode = "DE".try_into()?;

Accessors

Method Returns Example
value() &String "CZ"
into_inner() String "CZ"

Errors

Input Error
"" ValidationError::InvalidFormat
"USA" ValidationError::InvalidFormat (3 letters)
"C1" ValidationError::InvalidFormat (digit)

PhoneNumber

A validated phone number stored in canonical E.164 format.

Normalisation: non-digit characters stripped from the local number.
Validation: local number must be 4–14 digits. Calling code is derived from CountryCode.

use arvo::contact::{CountryCode, PhoneNumber, PhoneNumberInput};
use arvo::traits::{PrimitiveValue, ValueObject};

let phone = PhoneNumber::new(PhoneNumberInput {
    country_code: CountryCode::new("CZ".into())?,
    number: "123 456 789".into(),   // spaces stripped automatically
})?;

assert_eq!(phone.value(), "+420123456789");
assert_eq!(phone.calling_code(), "+420");
assert_eq!(phone.number(), "123456789");
assert_eq!(phone.country_code().value(), "CZ");

Accessors

Method Returns Example
value() &String "+420123456789"
calling_code() &str "+420"
number() &str "123456789"
country_code() &CountryCode CountryCode("CZ")
into_inner() PhoneNumberInput { country_code: "CZ", number: "123456789" }

Input struct

pub struct PhoneNumberInput {
    pub country_code: CountryCode,
    pub number: String,  // digits only; formatting characters are stripped
}

Errors

Input Error
number: "" ValidationError::InvalidFormat
number: "123" ValidationError::InvalidFormat (too short, min 4 digits)
number: "123456789012345" ValidationError::InvalidFormat (too long, max 14 digits)

Serde: serialises as a JSON object { "country_code": "CZ", "number": "123456789" } (the input struct).
TryFrom<&str>: not implemented — the E.164 canonical string cannot be unambiguously decoded back to structured PhoneNumberInput.


Website

A validated website URL. Accepts http and https schemes only. Scheme and host are normalised to lowercase on construction.

Normalisation: scheme and host lowercased.
Validation: must be a valid URL with http or https scheme and a host.

use arvo::contact::Website;
use arvo::traits::{PrimitiveValue, ValueObject};

let site = Website::new("https://EXAMPLE.COM/path".into())?;
assert_eq!(site.value(), "https://example.com/path");
assert!(site.is_https());
assert_eq!(site.host(), "example.com");

// try_into from &str
let site: Website = "https://example.com".try_into()?;

Accessors

Method Returns Example
value() &String "https://example.com/"
is_https() bool true
host() &str "example.com"
into_inner() String "https://example.com/"

Errors

Input Error
"" ValidationError::Empty
"not-a-url" ValidationError::InvalidFormat
"ftp://example.com" ValidationError::InvalidFormat (scheme not allowed)

PostalAddress

A validated composite postal address. All text fields are trimmed; empty or whitespace-only values are rejected. The country field requires a valid [CountryCode].

Normalisation: street, city, and zip are trimmed.
Validation: all fields must be non-empty after trimming.

use arvo::contact::{CountryCode, PostalAddress, PostalAddressInput};
use arvo::traits::{PrimitiveValue, ValueObject};

let addr = PostalAddress::new(PostalAddressInput {
    street:  "Václavské náměstí 1".into(),
    city:    "Prague".into(),
    zip:     "110 00".into(),
    country: CountryCode::new("CZ".into())?,
})?;

assert_eq!(addr.street(), "Václavské náměstí 1");
assert_eq!(addr.zip(), "110 00");
assert_eq!(addr.country().value(), "CZ");

// value() / Display — multi-line canonical form
assert_eq!(addr.value(), "Václavské náměstí 1\n110 00 Prague\nCZ");

Input struct

pub struct PostalAddressInput {
    pub street:  String,
    pub city:    String,
    pub zip:     String,
    pub country: CountryCode,
}

Accessors

Method Returns Example
value() &String "Main St 1\n10115 Berlin\nDE"
street() &str "Main St 1"
city() &str "Berlin"
zip() &str "10115"
country() &CountryCode CountryCode("DE")
into_inner() PostalAddressInput original input fields

Errors

Field Input Error
street "" or whitespace ValidationError::Empty
city "" or whitespace ValidationError::Empty
zip "" or whitespace ValidationError::Empty

Serde: serialises as a JSON object matching PostalAddressInput (the input struct).
TryFrom<&str>: not implemented — the formatted multi-line string cannot be unambiguously decoded back to structured fields.