package common import ( "fmt" "strings" ) // gameIDPrefix is the mandatory opaque-identifier prefix for one Game Lobby // game record. const gameIDPrefix = "game-" // applicationIDPrefix is the mandatory opaque-identifier prefix for one // Game Lobby application record. const applicationIDPrefix = "application-" // inviteIDPrefix is the mandatory opaque-identifier prefix for one Game // Lobby invite record. const inviteIDPrefix = "invite-" // membershipIDPrefix is the mandatory opaque-identifier prefix for one // Game Lobby membership record. const membershipIDPrefix = "membership-" // GameID identifies one game record owned by Game Lobby Service. The value // is opaque and stable; only its `game-*` prefix is observable to callers. type GameID string // String returns GameID as its stored identifier string. func (id GameID) String() string { return string(id) } // IsZero reports whether GameID does not contain a usable value. func (id GameID) IsZero() bool { return strings.TrimSpace(string(id)) == "" } // Validate reports whether GameID is non-empty, already trimmed, and carries // the frozen `game-*` opaque prefix. func (id GameID) Validate() error { return validatePrefixedID("game id", string(id), gameIDPrefix) } // ApplicationID identifies one application record owned by Game Lobby // Service. The value is opaque and stable; only its `application-*` prefix // is observable to callers. type ApplicationID string // String returns ApplicationID as its stored identifier string. func (id ApplicationID) String() string { return string(id) } // IsZero reports whether ApplicationID does not contain a usable value. func (id ApplicationID) IsZero() bool { return strings.TrimSpace(string(id)) == "" } // Validate reports whether ApplicationID is non-empty, already trimmed, and // carries the frozen `application-*` opaque prefix. func (id ApplicationID) Validate() error { return validatePrefixedID("application id", string(id), applicationIDPrefix) } // InviteID identifies one invite record owned by Game Lobby Service. The // value is opaque and stable; only its `invite-*` prefix is observable to // callers. type InviteID string // String returns InviteID as its stored identifier string. func (id InviteID) String() string { return string(id) } // IsZero reports whether InviteID does not contain a usable value. func (id InviteID) IsZero() bool { return strings.TrimSpace(string(id)) == "" } // Validate reports whether InviteID is non-empty, already trimmed, and // carries the frozen `invite-*` opaque prefix. func (id InviteID) Validate() error { return validatePrefixedID("invite id", string(id), inviteIDPrefix) } // MembershipID identifies one membership record owned by Game Lobby // Service. The value is opaque and stable; only its `membership-*` prefix // is observable to callers. type MembershipID string // String returns MembershipID as its stored identifier string. func (id MembershipID) String() string { return string(id) } // IsZero reports whether MembershipID does not contain a usable value. func (id MembershipID) IsZero() bool { return strings.TrimSpace(string(id)) == "" } // Validate reports whether MembershipID is non-empty, already trimmed, and // carries the frozen `membership-*` opaque prefix. func (id MembershipID) Validate() error { return validatePrefixedID("membership id", string(id), membershipIDPrefix) } // validatePrefixedID reports whether raw is a non-empty, trimmed identifier // with the given opaque prefix and a non-empty suffix. The label is used to // format error messages. func validatePrefixedID(label, raw, prefix string) error { switch { case strings.TrimSpace(raw) == "": return fmt.Errorf("%s must not be empty", label) case strings.TrimSpace(raw) != raw: return fmt.Errorf("%s must not contain surrounding whitespace", label) case !strings.HasPrefix(raw, prefix): return fmt.Errorf("%s must start with %q", label, prefix) case len(raw) == len(prefix): return fmt.Errorf("%s must carry a non-empty suffix after %q", label, prefix) default: return nil } }