github.com/iikira/iikira-go-utils@v0.0.0-20230610031953-f2cb11cde33a/utils/checksum/checksum_write.go (about) 1 package checksum 2 3 import ( 4 "hash" 5 "io" 6 ) 7 8 type ( 9 ChecksumWriter interface { 10 io.Writer 11 Sum() interface{} 12 } 13 14 ChecksumWriteUnit struct { 15 SliceEnd int64 16 End int64 17 SliceSum interface{} 18 Sum interface{} 19 OnlySliceSum bool 20 ChecksumWriter ChecksumWriter 21 22 ptr int64 23 } 24 25 hashChecksumWriter struct { 26 h hash.Hash 27 } 28 29 hash32ChecksumWriter struct { 30 h hash.Hash32 31 } 32 ) 33 34 func (wi *ChecksumWriteUnit) handleEnd() error { 35 if wi.ptr >= wi.End { 36 // 已写完 37 if !wi.OnlySliceSum { 38 wi.Sum = wi.ChecksumWriter.Sum() 39 } 40 return ErrChecksumWriteStop 41 } 42 return nil 43 } 44 45 func (wi *ChecksumWriteUnit) write(p []byte) (n int, err error) { 46 if wi.End <= 0 { 47 // do nothing 48 err = ErrChecksumWriteStop 49 return 50 } 51 err = wi.handleEnd() 52 if err != nil { 53 return 54 } 55 56 var ( 57 i int 58 left = wi.End - wi.ptr 59 lenP = len(p) 60 ) 61 if left < int64(lenP) { 62 // 读取即将完毕 63 i = int(left) 64 } else { 65 i = lenP 66 } 67 n, err = wi.ChecksumWriter.Write(p[:i]) 68 if err != nil { 69 return 70 } 71 wi.ptr += int64(n) 72 if left < int64(lenP) { 73 err = wi.handleEnd() 74 return 75 } 76 return 77 } 78 79 func (wi *ChecksumWriteUnit) Write(p []byte) (n int, err error) { 80 if wi.SliceEnd <= 0 { // 忽略Slice 81 // 读取全部 82 n, err = wi.write(p) 83 return 84 } 85 86 // 要计算Slice的情况 87 // 调整slice 88 if wi.SliceEnd > wi.End { 89 wi.SliceEnd = wi.End 90 } 91 92 // 计算剩余Slice 93 var ( 94 sliceLeft = wi.SliceEnd - wi.ptr 95 ) 96 if sliceLeft <= 0 { 97 // 已处理完Slice 98 if wi.OnlySliceSum { 99 err = ErrChecksumWriteStop 100 return 101 } 102 103 // 继续处理 104 n, err = wi.write(p) 105 return 106 } 107 108 var ( 109 lenP = len(p) 110 ) 111 if sliceLeft <= int64(lenP) { 112 var n1, n2 int 113 n1, err = wi.write(p[:sliceLeft]) 114 n += n1 115 if err != nil { 116 return 117 } 118 wi.SliceSum = wi.ChecksumWriter.Sum().([]byte) 119 n2, err = wi.write(p[sliceLeft:]) 120 n += n2 121 if err != nil { 122 return 123 } 124 return 125 } 126 n, err = wi.write(p) 127 return 128 } 129 130 func NewHashChecksumWriter(h hash.Hash) ChecksumWriter { 131 return &hashChecksumWriter{ 132 h: h, 133 } 134 } 135 136 func (hc *hashChecksumWriter) Write(p []byte) (n int, err error) { 137 return hc.h.Write(p) 138 } 139 140 func (hc *hashChecksumWriter) Sum() interface{} { 141 return hc.h.Sum(nil) 142 } 143 144 func NewHash32ChecksumWriter(h32 hash.Hash32) ChecksumWriter { 145 return &hash32ChecksumWriter{ 146 h: h32, 147 } 148 } 149 150 func (hc *hash32ChecksumWriter) Write(p []byte) (n int, err error) { 151 return hc.h.Write(p) 152 } 153 154 func (hc *hash32ChecksumWriter) Sum() interface{} { 155 return hc.h.Sum32() 156 }