You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
76 lines
2.3 KiB
76 lines
2.3 KiB
package testkit
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"io"
|
|
|
|
"g.activething.com/go/DateKeys/capsule"
|
|
)
|
|
|
|
// DiscardSink is a capsule.Sink that discards the files.
|
|
type DiscardSink struct{}
|
|
|
|
func (DiscardSink) Begin(*capsule.Head) error { return nil }
|
|
func (DiscardSink) Create(int) (io.WriteCloser, error) { return nopCloser{io.Discard}, nil }
|
|
func (DiscardSink) Commit() error { return nil }
|
|
func (DiscardSink) Abort() {}
|
|
|
|
type nopCloser struct{ io.Writer }
|
|
|
|
func (nopCloser) Close() error { return nil }
|
|
|
|
// MemorySink is a capsule.Sink that keeps the files in memory.
|
|
type MemorySink struct {
|
|
Head *capsule.Head
|
|
Files [][]byte
|
|
Committed bool
|
|
Aborted bool
|
|
}
|
|
|
|
func (s *MemorySink) Begin(h *capsule.Head) error {
|
|
s.Head, s.Files = h, make([][]byte, len(h.Files))
|
|
return nil
|
|
}
|
|
|
|
func (s *MemorySink) Create(i int) (io.WriteCloser, error) { return &memoryFile{s, i}, nil }
|
|
func (s *MemorySink) Commit() error { s.Committed = true; return nil }
|
|
func (s *MemorySink) Abort() { s.Aborted = true }
|
|
|
|
type memoryFile struct {
|
|
s *MemorySink
|
|
i int
|
|
}
|
|
|
|
func (f *memoryFile) Write(b []byte) (int, error) {
|
|
f.s.Files[f.i] = append(f.s.Files[f.i], b...)
|
|
return len(b), nil
|
|
}
|
|
|
|
func (f *memoryFile) Close() error { return nil }
|
|
|
|
// Head3 returns the head of the given files, laid out one after another in
|
|
// the order given, with their SHA-256, no mtime and a zero salt.
|
|
func Head3(comment, author string, paths []string, contents [][]byte) *capsule.Head {
|
|
h := &capsule.Head{Comment: comment, Author: author}
|
|
var end uint64
|
|
for i, p := range paths {
|
|
n := uint64(len(contents[i]))
|
|
h.Files = append(h.Files, capsule.File{Path: p, Size: n, Start: end, End: end + n, SHA256: sha256.Sum256(contents[i])})
|
|
end += n
|
|
}
|
|
return h
|
|
}
|
|
|
|
// Body3 assembles the BODY of a format 3 capsule (spec §29.2): the frame,
|
|
// security in an area of areaLen bytes, the head and the files.
|
|
func Body3(areaLen uint32, security, head []byte, contents ...[]byte) []byte {
|
|
frame := capsule.BodyFrame{AreaLen: areaLen, SecurityLen: uint32(len(security)), HeadLen: uint32(len(head))}.Bytes()
|
|
body := append(frame[:], security...)
|
|
body = append(body, make([]byte, int(areaLen)-len(security))...)
|
|
body = append(body, head...)
|
|
for _, c := range contents {
|
|
body = append(body, c...)
|
|
}
|
|
return body
|
|
}
|