拆分 JID(Go)

mellium.im/xmpp/jid 包实现的 JID 的操作。要将 JID 字符串拆分为其组成部分,可以使用 SplitString 函数:

lp, dp, rp, err := SplitString("romeo@example.net")

该功能不执行验证,并且不保证部件有效。

要手动拆分字符串而不依赖于 jid 包,底层代码如下所示:

// SplitString splits out the localpart, domainpart, and resourcepart from a
// string representation of a JID. The parts are not guaranteed to be valid, and
// each part must be 1023 bytes or less.
func SplitString(s string) (localpart, domainpart, resourcepart string, err error) {

    // RFC 7622 §3.1.  Fundamentals:
    //
    //    Implementation Note: When dividing a JID into its component parts,
    //    an implementation needs to match the separator characters '@' and
    //    '/' before applying any transformation algorithms, which might
    //    decompose certain Unicode code points to the separator characters.
    //
    // so let's do that now. First we'll parse the domainpart using the rules
    // defined in §3.2:
    //
    //    The domainpart of a JID is the portion that remains once the
    //    following parsing steps are taken:
    //
    //    1.  Remove any portion from the first '/' character to the end of the
    //        string (if there is a '/' character present).
    sep := strings.Index(s, "/")

    if sep == -1 {
        sep = len(s)
        resourcepart = ""
    } else {
        // If the resource part exists, make sure it isn't empty.
        if sep == len(s)-1 {
            err = errors.New("The resourcepart must be larger than 0 bytes")
            return
        }
        resourcepart = s[sep+1:]
        s = s[:sep]
    }

    //    2.  Remove any portion from the beginning of the string to the first
    //        '@' character (if there is an '@' character present).

    sep = strings.Index(s, "@")

    switch sep {
    case -1:
        // There is no @ sign, and therefore no localpart.
        localpart = ""
        domainpart = s
    case 0:
        // The JID starts with an @ sign (invalid empty localpart)
        err = errors.New("The localpart must be larger than 0 bytes")
        return
    default:
        domainpart = s[sep+1:]
        localpart = s[:sep]
    }

    // We'll throw out any trailing dots on domainparts, since they're ignored:
    //
    //    If the domainpart includes a final character considered to be a label
    //    separator (dot) by [RFC1034], this character MUST be stripped from
    //    the domainpart before the JID of which it is a part is used for the
    //    purpose of routing an XML stanza, comparing against another JID, or
    //    constructing an XMPP URI or IRI [RFC5122].  In particular, such a
    //    character MUST be stripped before any other canonicalization steps
    //    are taken.

    domainpart = strings.TrimSuffix(domainpart, ".")

    return
}