github.com/codingfuture/orig-energi3@v0.8.4/swarm/storage/feed/feed.go (about) 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 17 package feed 18 19 import ( 20 "hash" 21 "unsafe" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/common/hexutil" 25 "github.com/ethereum/go-ethereum/swarm/storage" 26 ) 27 28 // Feed represents a particular user's stream of updates on a topic 29 type Feed struct { 30 Topic Topic `json:"topic"` 31 User common.Address `json:"user"` 32 } 33 34 // Feed layout: 35 // TopicLength bytes 36 // userAddr common.AddressLength bytes 37 const feedLength = TopicLength + common.AddressLength 38 39 // mapKey calculates a unique id for this feed. Used by the cache map in `Handler` 40 func (f *Feed) mapKey() uint64 { 41 serializedData := make([]byte, feedLength) 42 f.binaryPut(serializedData) 43 hasher := hashPool.Get().(hash.Hash) 44 defer hashPool.Put(hasher) 45 hasher.Reset() 46 hasher.Write(serializedData) 47 hash := hasher.Sum(nil) 48 return *(*uint64)(unsafe.Pointer(&hash[0])) 49 } 50 51 // binaryPut serializes this feed instance into the provided slice 52 func (f *Feed) binaryPut(serializedData []byte) error { 53 if len(serializedData) != feedLength { 54 return NewErrorf(ErrInvalidValue, "Incorrect slice size to serialize feed. Expected %d, got %d", feedLength, len(serializedData)) 55 } 56 var cursor int 57 copy(serializedData[cursor:cursor+TopicLength], f.Topic[:TopicLength]) 58 cursor += TopicLength 59 60 copy(serializedData[cursor:cursor+common.AddressLength], f.User[:]) 61 cursor += common.AddressLength 62 63 return nil 64 } 65 66 // binaryLength returns the expected size of this structure when serialized 67 func (f *Feed) binaryLength() int { 68 return feedLength 69 } 70 71 // binaryGet restores the current instance from the information contained in the passed slice 72 func (f *Feed) binaryGet(serializedData []byte) error { 73 if len(serializedData) != feedLength { 74 return NewErrorf(ErrInvalidValue, "Incorrect slice size to read feed. Expected %d, got %d", feedLength, len(serializedData)) 75 } 76 77 var cursor int 78 copy(f.Topic[:], serializedData[cursor:cursor+TopicLength]) 79 cursor += TopicLength 80 81 copy(f.User[:], serializedData[cursor:cursor+common.AddressLength]) 82 cursor += common.AddressLength 83 84 return nil 85 } 86 87 // Hex serializes the feed to a hex string 88 func (f *Feed) Hex() string { 89 serializedData := make([]byte, feedLength) 90 f.binaryPut(serializedData) 91 return hexutil.Encode(serializedData) 92 } 93 94 // FromValues deserializes this instance from a string key-value store 95 // useful to parse query strings 96 func (f *Feed) FromValues(values Values) (err error) { 97 topic := values.Get("topic") 98 if topic != "" { 99 if err := f.Topic.FromHex(values.Get("topic")); err != nil { 100 return err 101 } 102 } else { // see if the user set name and relatedcontent 103 name := values.Get("name") 104 relatedContent, _ := hexutil.Decode(values.Get("relatedcontent")) 105 if len(relatedContent) > 0 { 106 if len(relatedContent) < storage.AddressLength { 107 return NewErrorf(ErrInvalidValue, "relatedcontent field must be a hex-encoded byte array exactly %d bytes long", storage.AddressLength) 108 } 109 relatedContent = relatedContent[:storage.AddressLength] 110 } 111 f.Topic, err = NewTopic(name, relatedContent) 112 if err != nil { 113 return err 114 } 115 } 116 f.User = common.HexToAddress(values.Get("user")) 117 return nil 118 } 119 120 // AppendValues serializes this structure into the provided string key-value store 121 // useful to build query strings 122 func (f *Feed) AppendValues(values Values) { 123 values.Set("topic", f.Topic.Hex()) 124 values.Set("user", f.User.Hex()) 125 }