+func (mth *MTHSeq) PreaddFrom(r io.Reader, pktName string, showPrgrs bool) (int64, error) {
+ if mth.finished {
+ return 0, errors.New("already Sum()ed")
+ }
+ if mth.buf.Len() > 0 {
+ if _, err := mth.hasherLeaf.Write(mth.buf.Next(MTHBlockSize)); err != nil {
+ panic(err)
+ }
+ mth.leafAdd()
+ mth.fold()
+ }
+ prevHashes := mth.hashes
+ mth.hashes = nil
+ prevCtr := mth.ctr
+ mth.ctr = 0
+ lr := io.LimitedReader{R: r, N: mth.prependSize}
+ les := LEs{{"Pkt", pktName}, {"FullSize", mth.prependSize}}
+ n, err := CopyProgressed(mth, &lr, "prehash", les, showPrgrs)
+ for _, ent := range prevHashes {
+ mth.hashes = append(mth.hashes, ent)
+ mth.fold()
+ }
+ if mth.buf.Len() > 0 {
+ mth.ctr = prevCtr - 1
+ } else {
+ mth.ctr = prevCtr
+ }
+ return n, err
+}
+
+func (mth *MTHSeq) Events() chan MTHEvent {
+ mth.events = make(chan MTHEvent)
+ return mth.events
+}
+
+func (mth *MTHSeq) PreaddSize() int64 { return mth.prependSize }
+
+func (mth *MTHSeq) leafAdd() {
+ ent := MTHSeqEnt{c: mth.ctr}
+ mth.hasherLeaf.Sum(ent.h[:0])
+ mth.hasherLeaf.Reset()
+ mth.hashes = append(mth.hashes, ent)
+ mth.ctr++
+ if mth.events != nil {
+ mth.events <- MTHEvent{MTHEventAdd, &ent}
+ }
+}
+
+func (mth *MTHSeq) fold() {
+ for len(mth.hashes) >= 2 {
+ hlen := len(mth.hashes)
+ end1 := &mth.hashes[hlen-2]
+ end0 := &mth.hashes[hlen-1]
+ if end1.c%2 == 1 {
+ break
+ }
+ if end1.l != end0.l {
+ break
+ }
+ if _, err := mth.hasherNode.Write(end1.h[:]); err != nil {
+ panic(err)
+ }
+ if _, err := mth.hasherNode.Write(end0.h[:]); err != nil {
+ panic(err)
+ }
+ mth.hashes = mth.hashes[:hlen-1]
+ end1.l++
+ end1.c /= 2
+ mth.hasherNode.Sum(end1.h[:0])
+ mth.hasherNode.Reset()
+ if mth.events != nil {
+ mth.events <- MTHEvent{MTHEventFold, end1}
+ }
+ }
+}
+
+func (mth *MTHSeq) Write(data []byte) (int, error) {