diff options
Diffstat (limited to 'pkg/midipak/midipak.go')
-rw-r--r-- | pkg/midipak/midipak.go | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/pkg/midipak/midipak.go b/pkg/midipak/midipak.go new file mode 100644 index 0000000..19ccde3 --- /dev/null +++ b/pkg/midipak/midipak.go @@ -0,0 +1,55 @@ +// midipak implements compressing and appending MIDI flles +// to a midipak file. +package midipak + +import ( + "context" + "database/sql" +) + +// Encoder compresses each of the input files, +// and is expected to be goroutine safe. +type Encoder interface { + EncodeAll(src, dst []byte) []byte +} + +// File stores the name and data of a file. +type File struct { + Name string + Data []byte +} + +// Create initializes a new midipak. +func Create(ctx context.Context, db *sql.DB) error { + sqlStmt := "CREATE TABLE files (name TEXT PRIMARY KEY, sz INTEGER NOT NULL, data BLOB);" + + _, err := db.ExecContext(ctx, sqlStmt) + return err +} + +// Pack appends the files to the midipak, after being compressed +// with the provided encoder. Attempting to pack files that already +// exist is an error. +func Pack(ctx context.Context, db *sql.DB, enc Encoder, files []File) error { + tx, err := db.BeginTx(ctx, nil) + if err != nil { + return err + } + + stmt, err := tx.Prepare("INSERT INTO files(name, sz, data) VALUES (?, ?, ?)") + if err != nil { + return err + } + defer stmt.Close() + + for _, file := range files { + sz := len(file.Data) + + _, err = stmt.Exec(file.Name, sz, enc.EncodeAll(file.Data, make([]byte, 0, sz))) + if err != nil { + return err + } + } + + return tx.Commit() +} |