blob: b89323062c280f2b91c4a974edc1684f6a3e9315 [file] [log] [blame]
package diffstore
import (
"fmt"
"image"
"strings"
"go.skia.org/infra/go/fileutil"
"go.skia.org/infra/go/util"
"go.skia.org/infra/golden/go/diff"
"go.skia.org/infra/golden/go/types"
"go.skia.org/infra/golden/go/validation"
)
const (
// DIFF_IMG_SEPARATOR is the character that separates two image ids in the
// resulting diff image.
DIFF_IMG_SEPARATOR = "-"
)
// GoldIDPathMapper implements the DiffStoreMapper interface. It translates
// between digests (image ids) and storage paths. It uses diff.DiffMetrics
// as the Gold diff metric.
type GoldDiffStoreMapper struct {
util.LRUCodec
}
// NewGoldDiffStoreMapper returns a new instance of GoldDiffStoreMapper that uses
// a JSON coded to serialize/deserialize instances of diff.DiffMetrics.
func NewGoldDiffStoreMapper(diffInstance interface{}) DiffStoreMapper {
return GoldDiffStoreMapper{LRUCodec: util.JSONCodec(diffInstance)}
}
// DiffFn implements the DiffStoreMapper interface.
func (g GoldDiffStoreMapper) DiffFn(leftImg *image.NRGBA, rightImg *image.NRGBA) (interface{}, *image.NRGBA) {
return diff.DefaultDiffFn(leftImg, rightImg)
}
// DiffID implements the DiffStoreMapper interface.
func (g GoldDiffStoreMapper) DiffID(leftImgID, rightImgID types.Digest) string {
_, _, diffID := g.getOrderedDiffID(leftImgID, rightImgID)
return diffID
}
// SplitDiffID implements the DiffStoreMapper interface.
func (g GoldDiffStoreMapper) SplitDiffID(diffID string) (types.Digest, types.Digest) {
imageIDs := strings.Split(diffID, DIFF_IMG_SEPARATOR)
// TODO(stephana): Remove this legacy handling code as soon as it has converted the
// database in production.
if strings.Contains(diffID, ":") {
imageIDs = strings.Split(diffID, ":")
}
return types.Digest(imageIDs[0]), types.Digest(imageIDs[1])
}
// SplitDiffID implements the DiffStoreMapper interface.
func (g GoldDiffStoreMapper) DiffPath(leftImgDigest, rightImgDigest types.Digest) string {
// Get the diff ID and the left imageID.
_, _, diffID := g.getOrderedDiffID(leftImgDigest, rightImgDigest)
imagePath := fmt.Sprintf("%s.%s", diffID, IMG_EXTENSION)
return fileutil.TwoLevelRadixPath(imagePath)
}
// ImagePaths implements the DiffStoreMapper interface.
func (g GoldDiffStoreMapper) ImagePaths(imageID types.Digest) (string, string, string) {
gsPath := fmt.Sprintf("%s.%s", imageID, IMG_EXTENSION)
localPath := fileutil.TwoLevelRadixPath(gsPath)
return localPath, "", gsPath
}
// IsValidDiffImgIDimplements the DiffStoreMapper interface.
func (g GoldDiffStoreMapper) IsValidDiffImgID(diffImgID string) bool {
imageIDs := strings.Split(diffImgID, DIFF_IMG_SEPARATOR)
if len(imageIDs) != 2 {
return false
}
return g.IsValidImgID(imageIDs[0]) && g.IsValidImgID(imageIDs[1])
}
// IsValidImgIDimplements the DiffStoreMapper interface.
func (g GoldDiffStoreMapper) IsValidImgID(imgID string) bool {
return validation.IsValidDigest(imgID)
}
func (g GoldDiffStoreMapper) getOrderedDiffID(leftImgID, rightImgID types.Digest) (types.Digest, types.Digest, string) {
if rightImgID < leftImgID {
// Make sure the smaller digest is left imageID.
leftImgID, rightImgID = rightImgID, leftImgID
}
return leftImgID, rightImgID, string(leftImgID) + DIFF_IMG_SEPARATOR + string(rightImgID)
}