// 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() }