func EventKeyFromRpc(key *any.Any) (interface{}, error) {
  if key == nil {
    return nil, nil
  }
  obj := &ptypes.DynamicAny{}
  err := ptypes.UnmarshalAny(key, obj)
  if err != nil {
    return nil, err
  }
  profileId, ok := obj.Message.(*ProfileIdKey)
  if ok {
    return &entity.ProfileIdKey{
      Name: profileId.Name,
      At:   time.Unix(profileId.At, 0),
    }, nil
  }
  id, ok := obj.Message.(*IdKey)
  if ok {
    i, err := uuid.Parse(id.Id)
    return &i, err
  }
  return nil, fmt.Errorf("unknown key type: %v", obj.Message)
}
decodes an arbitrary key type from its rpc representation
package rpc
import (
  "errors"
  "fmt"
  "time"
  "github.com/dotStart/Stockpile/entity"
  "github.com/dotStart/Stockpile/stockpile/plugin"
  "github.com/golang/protobuf/proto"
  "github.com/golang/protobuf/ptypes"
  "github.com/golang/protobuf/ptypes/any"
  "github.com/google/uuid"
)
const MessageTypeBaseUrl = "github.com/dotStart/Stockpile/stockpile/server/rpc/"
func ProfileIdFromRpc(rpc *ProfileId) (*entity.ProfileId, error) {
  if !rpc.IsPopulated() {
    return nil, nil
  }
  id, err := uuid.Parse(rpc.Id)
  if err != nil {
    return nil, err
  }
  return &entity.ProfileId{
    Id:          id,
    Name:        rpc.Name,
    FirstSeenAt: time.Unix(rpc.FirstSeenAt, 0),
    LastSeenAt:  time.Unix(rpc.LastSeenAt, 0),
    ValidUntil:  time.Unix(rpc.ValidUntil, 0),
  }, nil
}
func ProfileIdsFromRpcArray(rpc []*ProfileId) ([]*entity.ProfileId, error) {
  arr := make([]*entity.ProfileId, len(rpc))
  for i, encoded := range rpc {
    profileId, err := ProfileIdFromRpc(encoded)
    if err != nil {
      return nil, err
    }
    if profileId == nil {
      return nil, errors.New("encountered one or more unpopulated profiles in response")
    }
    arr[i] = profileId
  }
  return arr, nil
}
func ProfileIdToRpc(profileId *entity.ProfileId) *ProfileId {
  return &ProfileId{
    Id:          profileId.Id.String(),
    Name:        profileId.Name,
    FirstSeenAt: profileId.FirstSeenAt.Unix(),
    LastSeenAt:  profileId.LastSeenAt.Unix(),
    ValidUntil:  profileId.ValidUntil.Unix(),
  }
}
func ProfileIdsToRpcArray(profileIds []*entity.ProfileId) []*ProfileId {
  arr := make([]*ProfileId, len(profileIds))
  for i, profileId := range profileIds {
    arr[i] = ProfileIdToRpc(profileId)
  }
  return arr
}
func NameChangeToRpc(change *entity.NameChange) *NameHistoryEntry {
  return &NameHistoryEntry{
    Name:        change.Name,
    ChangedToAt: change.ChangedToAt.Unix(),
    ValidUntil:  change.ValidUntil.Unix(),
  }
}
func NameChangesToRpcArray(changes []*entity.NameChange) []*NameHistoryEntry {
  arr := make([]*NameHistoryEntry, len(changes))
  for i, change := range changes {
    arr[i] = NameChangeToRpc(change)
  }
  return arr
}
func NameChangeFromRpc(rpc *NameHistoryEntry) *entity.NameChange {
  return &entity.NameChange{
    Name:        rpc.Name,
    ChangedToAt: time.Unix(rpc.ChangedToAt, 0),
    ValidUntil:  time.Unix(rpc.ValidUntil, 0),
  }
}
func NameChangesFromRpcArray(rpc []*NameHistoryEntry) []*entity.NameChange {
  arr := make([]*entity.NameChange, len(rpc))
  for i, change := range rpc {
    arr[i] = NameChangeFromRpc(change)
  }
  return arr
}
func NameHistoryToRpc(history *entity.NameChangeHistory) *NameHistory {
  if history == nil || len(history.History) == 0 {
    return &NameHistory{}
  }
  return &NameHistory{
    History: NameChangesToRpcArray(history.History),
  }
}
func NameHistoryFromRpc(history *NameHistory) *entity.NameChangeHistory {
  if !history.IsPopulated() {
    return nil
  }
  return &entity.NameChangeHistory{
    History: NameChangesFromRpcArray(history.History),
  }
}
func BulkIdsToRpc(ids []*entity.ProfileId) *BulkIdResponse {
  if ids == nil || len(ids) == 0 {
    return &BulkIdResponse{}
  }
  return &BulkIdResponse{
    Ids: ProfileIdsToRpcArray(ids),
  }
}
func BulkIdsFromRpc(rpc *BulkIdResponse) ([]*entity.ProfileId, error) {
  if !rpc.IsPopulated() {
    return nil, nil
  }
  return ProfileIdsFromRpcArray(rpc.Ids)
}
func ProfileToRpc(profile *entity.Profile) *Profile {
  var tex *ProfileTextures = nil
  if profile.Textures != nil {
    tex = ProfileTexturesToRpc(profile.Textures)
  }
  return &Profile{
    Id:         profile.Id.String(),
    Name:       profile.Name,
    Properties: ProfilePropertiesToRpcArray(profile.Properties),
    Textures:   tex,
  }
}
func ProfileFromRpc(rpc *Profile) (*entity.Profile, error) {
  id, err := uuid.Parse(rpc.Id)
  if err != nil {
    return nil, err
  }
  var tex *entity.ProfileTextures
  if rpc.Textures != nil {
    tex, err = ProfileTexturesFromRpc(rpc.Textures)
    if err != nil {
      return nil, err
    }
  }
  return &entity.Profile{
    Id:         id,
    Name:       rpc.Name,
    Properties: ProfilePropertiesFromRpcArray(rpc.Properties),
    Textures:   tex,
  }, nil
}
func ProfilePropertiesToRpcArray(props map[string]*entity.ProfileProperty) []*ProfileProperty {
  arr := make([]*ProfileProperty, 0)
  for _, prop := range props {
    arr = append(arr, ProfilePropertyToRpc(prop))
  }
  return arr
}
func ProfilePropertiesFromRpcArray(rpc []*ProfileProperty) map[string]*entity.ProfileProperty {
  arr := make(map[string]*entity.ProfileProperty)
  for _, prop := range rpc {
    arr[prop.Name] = ProfilePropertyFromRpc(prop)
  }
  return arr
}
func ProfilePropertyToRpc(prop *entity.ProfileProperty) *ProfileProperty {
  return &ProfileProperty{
    Name:      prop.Name,
    Value:     prop.Value,
    Signature: prop.Signature,
  }
}
func ProfilePropertyFromRpc(rpc *ProfileProperty) *entity.ProfileProperty {
  return &entity.ProfileProperty{
    Name:      rpc.Name,
    Value:     rpc.Value,
    Signature: rpc.Signature,
  }
}
func ProfileTexturesToRpc(tex *entity.ProfileTextures) *ProfileTextures {
  return &ProfileTextures{
    ProfileId:   tex.ProfileId.String(),
    ProfileName: tex.ProfileName,
    SkinUrl:     tex.Textures["SKIN"],  
    CapeUrl:     tex.Textures["CAPE"],
    Timestamp:   tex.Timestamp.Unix(),
  }
}
func ProfileTexturesFromRpc(rpc *ProfileTextures) (*entity.ProfileTextures, error) {
  id, err := uuid.Parse(rpc.ProfileId)
  if err != nil {
    return nil, err
  }
  textures := make(map[string]string)
  textures["SKIN"] = rpc.SkinUrl
  textures["CAPE"] = rpc.CapeUrl
  return &entity.ProfileTextures{
    Timestamp:   time.Unix(rpc.Timestamp, 0),
    ProfileId:   id,
    ProfileName: rpc.ProfileName,
    Textures:    textures,
  }, nil
}
func BlacklistToRpc(blacklist *entity.Blacklist) *Blacklist {
  return &Blacklist{
    Hashes: blacklist.Hashes,
  }
}
func BlacklistFromRpc(blacklist *Blacklist) (*entity.Blacklist, error) {
  return entity.NewBlacklist(blacklist.Hashes)
}
func EventToRpc(event *entity.Event) (*Event, error) {
  key, err := EventKeyToRpc(event.Key)
  if err != nil {
    return nil, err
  }
  obj, err := EventPayloadToRpc(event.Object)
  if err != nil {
    return nil, err
  }
  enc, err := ptypes.MarshalAny(obj)
  if err != nil {
    return nil, err
  }
  return &Event{
    Type:   EventTypeToRpc(event.Type),
    Key:    key,
    Object: enc,
  }, nil
}
func EventFromRpc(event *Event) (*entity.Event, error) {
  typ, err := EventTypeFromRpc(event.Type)
  if err != nil {
    return nil, err
  }
  key, err := EventKeyFromRpc(event.Key)
  if err != nil {
    return nil, err
  }
  payload, err := EventPayloadFromRpc(event.Object)
  if err != nil {
    return nil, err
  }
  return &entity.Event{
    Type:   typ,
    Key:    key,
    Object: payload,
  }, nil
}
func EventTypeToRpc(typ entity.EventType) EventType {
  switch typ {
  case entity.ProfileIdEvent:
    return EventType_PROFILE_ID
  case entity.NameHistoryEvent:
    return EventType_NAME_HISTORY
  case entity.ProfileEvent:
    return EventType_PROFILE
  case entity.BlacklistEvent:
    return EventType_BLACKLIST
  default:
    return -1  
  }
}
func EventTypeFromRpc(typ EventType) (entity.EventType, error) {
  switch typ {
  case EventType_PROFILE_ID:
    return entity.ProfileIdEvent, nil
  case EventType_NAME_HISTORY:
    return entity.NameHistoryEvent, nil
  case EventType_PROFILE:
    return entity.ProfileEvent, nil
  case EventType_BLACKLIST:
    return entity.BlacklistEvent, nil
  default:
    return -1, fmt.Errorf("illegal event type: %d", typ)
  }
}
func EventKeyToRpc(key interface{}) (*any.Any, error) {
  if key == nil {
    return nil, nil
  }
  profileId, ok := key.(*entity.ProfileIdKey)
  if ok {
    return ptypes.MarshalAny(&ProfileIdKey{
      Name: profileId.Name,
      At:   profileId.At.Unix(),
    })
  }
  id, ok := key.(*uuid.UUID)
  if ok {
    return ptypes.MarshalAny(&IdKey{
      Id: id.String(),
    })
  }
  return nil, fmt.Errorf("unknown key type: %v", key)
}