// Address forms (SPEC.md §3): parsing goes through the native library, so // the username rules are fumi's, not a reimplementation that can drift. import "package:smol_mail/native/ffi.dart"; import "package:smol_mail/smol/errors.dart"; /// One parsed address. [identity] carries the self-certifying key a /// smol:// URI binds; a short form has none until it is resolved. class SmolAddress { final String user; final String host; final int port; final String? identity; final bool rns; const SmolAddress(this.user, this.host, this.port, {this.identity, this.rns = false}); /// The short form a contact list shows; the default port is elided. String get short => rns ? "smol+rns://$user@$host" : "$user@$host${port == defaultPort ? "" : ":$port"}"; /// The self-certifying form: the key inside makes the address verifiable. String uri(String publicKey) => rns ? "smol+rns://$user@$host/$publicKey" : "smol://$user@$host${port == defaultPort ? "" : ":$port"}/$publicKey"; } const defaultPort = 1961; /// Parses any of the four address forms. Throws [SmolError] on anything /// else — the onboarding and compose fields validate through this. SmolAddress parseAddress(String text) { final Map parsed; try { parsed = SmolFfi.open().parseAddress(text.trim()); } on NativeSmolException catch (err) { throw SmolError(err.message); } return SmolAddress( parsed["user"] as String, parsed["host"] as String, parsed["port"] as int, identity: parsed["identity"] as String?, rns: parsed["scheme"] == "rns", ); }