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 }