pub struct ContractIdParts {
pub country_code: String,
pub provider_id: String,
pub instance: String,
pub check_digit: Option<char>,
}Expand description
The parts of an eMI3/IDACS Contract ID (eMAID), when it follows the recommended format.
Recommended to follow the specification for eMA ID from “E-mobility ID-codes: the purpose of IDs, ID usage and ID format”.
The format is <country><provider><instance>[<check>]: two letters, three alphanumerics, nine
alphanumerics, and an optional check character. A hyphen may separate all three positions —
“if the hyphenated representation is chosen, the separators must be set at all three
places” — and is for human reading only; the IDACS white paper advises against sending it
between systems.
This is what makes a whitelist match. contract_id is a CiString, so case already does
not matter, but DE-8AA-CA2B3C4D5-N and DE8AACA2B3C4D5N are the same contract written two
ways, and comparing the strings says they are not. normalise folds both to
one key.
Like EvseIdParts, parsing is a query rather than a requirement: the format is recommended
by OCPI, not mandated, so an id in any other shape returns None and the crate carries on.
§What this cannot tell you
The format has no marker to match on — it is “two letters, then twelve or thirteen
alphanumerics” — so any id of that shape parses, including one that is not an eMAID at all.
some-internal-id is fourteen characters once the hyphens go, and comes back as a contract in
SO issued by provider MEI.
That costs a whitelist nothing, because normalise is a function: the
same id always folds to the same key, whether or not it was really an eMAID. It does mean
party is only meaningful for an id you already know follows the format. The
instance conventionally begins with C — “strongly recommended to use the type-ID C as first
character” — which is a useful signal, but a recommendation is not something this crate will
reject a conformant id over.
use ocpi_kit::types::ContractIdParts;
let parts = ContractIdParts::parse("DE-8AA-CA2B3C4D5-N").unwrap();
assert_eq!(parts.country_code, "DE");
assert_eq!(parts.provider_id, "8AA");
assert_eq!(parts.instance, "CA2B3C4D5");
assert_eq!(parts.check_digit, Some('N'));
// The same contract, written three ways, folds to one key.
let key = ContractIdParts::normalise("DE-8AA-CA2B3C4D5-N").unwrap();
assert_eq!(key, "DE8AACA2B3C4D5N");
assert_eq!(ContractIdParts::normalise("de8aaca2b3c4d5n").unwrap(), key);
assert_eq!(ContractIdParts::normalise("DE*8AA*CA2B3C4D5*N").unwrap(), key);
// Anything not of that shape is `None`, and so is anything too short or too long.
assert!(ContractIdParts::parse("DE8AA").is_none());
assert!(ContractIdParts::parse("12-8AA-CA2B3C4D5-N").is_none()); // country is not lettersSpec: 2.3.0 §mod_cdrs_cdr_token_class, §mod_tokens_token_object
Fields§
§country_code: StringThe two-letter ISO 3166-1 alpha-2 country code of the provider.
provider_id: StringThe three-character provider ID, assigned by the eMI3 group.
instance: StringThe nine-character instance, whose first character is conventionally C.
check_digit: Option<char>The check character, which the format marks optional.
Implementations§
Source§impl ContractIdParts
impl ContractIdParts
Sourcepub fn parse(id: &str) -> Option<Self>
pub fn parse(id: &str) -> Option<Self>
Parses an eMI3/IDACS contract ID, or returns None if id is in another shape.
Both separators seen in the field are accepted — -, which the contract-ID format
specifies, and *, which the EVSE-ID format uses and which some platforms carry over.
Sourcepub fn normalise(id: &str) -> Option<String>
pub fn normalise(id: &str) -> Option<String>
The one key two spellings of the same contract share: upper case, no separators.
This is the form to key a whitelist on. Returns None for an id that does not follow the
format, which a caller should treat as “not comparable” rather than as “no match” — an
eMSP is free to use its own scheme.
Sourcepub fn party(&self) -> Result<PartyRef, InvalidString>
pub fn party(&self) -> Result<PartyRef, InvalidString>
The provider that issued this contract, according to the ID.
As with EvseIdParts::party, this need not be the OCPI party_id that pushed the
object: “The party_id and country_code given here have no direct link with the
eMI3/IDACS format EVSE IDs and Contract IDs.”
§Errors
Returns InvalidString if the parts are not valid CiStrings, which cannot happen for
a value that came out of ContractIdParts::parse.
Sourcepub fn to_compact(&self) -> String
pub fn to_compact(&self) -> String
The ID with no separators and in upper case: DE8AACA2B3C4D5N.
Companies are strongly advised NOT to use the optional separators between IT systems as they are meant for visibility only.
Sourcepub fn to_separated(&self) -> String
pub fn to_separated(&self) -> String
The ID in the hyphenated form a human reads: DE-8AA-CA2B3C4D5-N.
Trait Implementations§
Source§impl Clone for ContractIdParts
impl Clone for ContractIdParts
Source§fn clone(&self) -> ContractIdParts
fn clone(&self) -> ContractIdParts
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ContractIdParts
impl Debug for ContractIdParts
impl Eq for ContractIdParts
Source§impl PartialEq for ContractIdParts
impl PartialEq for ContractIdParts
impl StructuralPartialEq for ContractIdParts
Auto Trait Implementations§
impl Freeze for ContractIdParts
impl RefUnwindSafe for ContractIdParts
impl Send for ContractIdParts
impl Sync for ContractIdParts
impl Unpin for ContractIdParts
impl UnsafeUnpin for ContractIdParts
impl UnwindSafe for ContractIdParts
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.