feed.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // Copyright 2018 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package feed
  17. import (
  18. "hash"
  19. "unsafe"
  20. "github.com/ethereum/go-ethereum/common"
  21. "github.com/ethereum/go-ethereum/common/hexutil"
  22. "github.com/ethereum/go-ethereum/swarm/storage"
  23. )
  24. // Feed represents a particular user's stream of updates on a topic
  25. type Feed struct {
  26. Topic Topic `json:"topic"`
  27. User common.Address `json:"user"`
  28. }
  29. // Feed layout:
  30. // TopicLength bytes
  31. // userAddr common.AddressLength bytes
  32. const feedLength = TopicLength + common.AddressLength
  33. // mapKey calculates a unique id for this feed. Used by the cache map in `Handler`
  34. func (f *Feed) mapKey() uint64 {
  35. serializedData := make([]byte, feedLength)
  36. f.binaryPut(serializedData)
  37. hasher := hashPool.Get().(hash.Hash)
  38. defer hashPool.Put(hasher)
  39. hasher.Reset()
  40. hasher.Write(serializedData)
  41. hash := hasher.Sum(nil)
  42. return *(*uint64)(unsafe.Pointer(&hash[0]))
  43. }
  44. // binaryPut serializes this feed instance into the provided slice
  45. func (f *Feed) binaryPut(serializedData []byte) error {
  46. if len(serializedData) != feedLength {
  47. return NewErrorf(ErrInvalidValue, "Incorrect slice size to serialize feed. Expected %d, got %d", feedLength, len(serializedData))
  48. }
  49. var cursor int
  50. copy(serializedData[cursor:cursor+TopicLength], f.Topic[:TopicLength])
  51. cursor += TopicLength
  52. copy(serializedData[cursor:cursor+common.AddressLength], f.User[:])
  53. cursor += common.AddressLength
  54. return nil
  55. }
  56. // binaryLength returns the expected size of this structure when serialized
  57. func (f *Feed) binaryLength() int {
  58. return feedLength
  59. }
  60. // binaryGet restores the current instance from the information contained in the passed slice
  61. func (f *Feed) binaryGet(serializedData []byte) error {
  62. if len(serializedData) != feedLength {
  63. return NewErrorf(ErrInvalidValue, "Incorrect slice size to read feed. Expected %d, got %d", feedLength, len(serializedData))
  64. }
  65. var cursor int
  66. copy(f.Topic[:], serializedData[cursor:cursor+TopicLength])
  67. cursor += TopicLength
  68. copy(f.User[:], serializedData[cursor:cursor+common.AddressLength])
  69. cursor += common.AddressLength
  70. return nil
  71. }
  72. // Hex serializes the feed to a hex string
  73. func (f *Feed) Hex() string {
  74. serializedData := make([]byte, feedLength)
  75. f.binaryPut(serializedData)
  76. return hexutil.Encode(serializedData)
  77. }
  78. // FromValues deserializes this instance from a string key-value store
  79. // useful to parse query strings
  80. func (f *Feed) FromValues(values Values) (err error) {
  81. topic := values.Get("topic")
  82. if topic != "" {
  83. if err := f.Topic.FromHex(values.Get("topic")); err != nil {
  84. return err
  85. }
  86. } else { // see if the user set name and relatedcontent
  87. name := values.Get("name")
  88. relatedContent, _ := hexutil.Decode(values.Get("relatedcontent"))
  89. if len(relatedContent) > 0 {
  90. if len(relatedContent) < storage.AddressLength {
  91. return NewErrorf(ErrInvalidValue, "relatedcontent field must be a hex-encoded byte array exactly %d bytes long", storage.AddressLength)
  92. }
  93. relatedContent = relatedContent[:storage.AddressLength]
  94. }
  95. f.Topic, err = NewTopic(name, relatedContent)
  96. if err != nil {
  97. return err
  98. }
  99. }
  100. f.User = common.HexToAddress(values.Get("user"))
  101. return nil
  102. }
  103. // AppendValues serializes this structure into the provided string key-value store
  104. // useful to build query strings
  105. func (f *Feed) AppendValues(values Values) {
  106. values.Set("topic", f.Topic.Hex())
  107. values.Set("user", f.User.Hex())
  108. }