diff --git a/persistence/playlist_track_repository.go b/persistence/playlist_track_repository.go index 33017b90..24715a17 100644 --- a/persistence/playlist_track_repository.go +++ b/persistence/playlist_track_repository.go @@ -5,7 +5,7 @@ import ( "github.com/deluan/rest" "github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/model" - "github.com/navidrome/navidrome/utils" + "github.com/navidrome/navidrome/utils/slice" ) type playlistTrackRepository struct { @@ -196,7 +196,7 @@ func (r *playlistTrackRepository) Reorder(pos int, newPos int) error { if err != nil { return err } - newOrder := utils.MoveString(ids, pos-1, newPos-1) + newOrder := slice.Move(ids, pos-1, newPos-1) return r.playlistRepo.updatePlaylist(r.playlistId, newOrder) } diff --git a/utils/slice/slice.go b/utils/slice/slice.go index 60606020..cd012330 100644 --- a/utils/slice/slice.go +++ b/utils/slice/slice.go @@ -41,3 +41,16 @@ func MostFrequent[T comparable](list []T) T { return topItem } + +func Insert[T any](slice []T, value T, index int) []T { + return append(slice[:index], append([]T{value}, slice[index:]...)...) +} + +func Remove[T any](slice []T, index int) []T { + return append(slice[:index], slice[index+1:]...) +} + +func Move[T any](slice []T, srcIndex int, dstIndex int) []T { + value := slice[srcIndex] + return Insert(Remove(slice, srcIndex), value, dstIndex) +} diff --git a/utils/slice/slice_test.go b/utils/slice/slice_test.go index 7a33e01d..a27416f3 100644 --- a/utils/slice/slice_test.go +++ b/utils/slice/slice_test.go @@ -14,45 +14,59 @@ func TestSlice(t *testing.T) { RunSpecs(t, "Slice Suite") } -var _ = Describe("Map", func() { - It("returns empty slice for an empty input", func() { - mapFunc := func(v int) string { return strconv.Itoa(v * 2) } - result := slice.Map([]int{}, mapFunc) - Expect(result).To(BeEmpty()) +var _ = Describe("Slice Utils", func() { + Describe("Map", func() { + It("returns empty slice for an empty input", func() { + mapFunc := func(v int) string { return strconv.Itoa(v * 2) } + result := slice.Map([]int{}, mapFunc) + Expect(result).To(BeEmpty()) + }) + + It("returns a new slice with elements mapped", func() { + mapFunc := func(v int) string { return strconv.Itoa(v * 2) } + result := slice.Map([]int{1, 2, 3, 4}, mapFunc) + Expect(result).To(ConsistOf("2", "4", "6", "8")) + }) }) - It("returns a new slice with elements mapped", func() { - mapFunc := func(v int) string { return strconv.Itoa(v * 2) } - result := slice.Map([]int{1, 2, 3, 4}, mapFunc) - Expect(result).To(ConsistOf("2", "4", "6", "8")) - }) -}) - -var _ = Describe("Group", func() { - It("returns empty map for an empty input", func() { - keyFunc := func(v int) int { return v % 2 } - result := slice.Group([]int{}, keyFunc) - Expect(result).To(BeEmpty()) - }) - - It("groups by the result of the key function", func() { - keyFunc := func(v int) int { return v % 2 } - result := slice.Group([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, keyFunc) - Expect(result).To(HaveLen(2)) - Expect(result[0]).To(ConsistOf(2, 4, 6, 8, 10)) - Expect(result[1]).To(ConsistOf(1, 3, 5, 7, 9, 11)) - }) -}) - -var _ = Describe("MostFrequent", func() { - It("returns zero value if no arguments are passed", func() { - Expect(slice.MostFrequent([]int{})).To(BeZero()) - }) - - It("returns the single item", func() { - Expect(slice.MostFrequent([]string{"123"})).To(Equal("123")) - }) - It("returns the item that appeared more times", func() { - Expect(slice.MostFrequent([]string{"1", "2", "1", "2", "3", "2"})).To(Equal("2")) + Describe("Group", func() { + It("returns empty map for an empty input", func() { + keyFunc := func(v int) int { return v % 2 } + result := slice.Group([]int{}, keyFunc) + Expect(result).To(BeEmpty()) + }) + + It("groups by the result of the key function", func() { + keyFunc := func(v int) int { return v % 2 } + result := slice.Group([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, keyFunc) + Expect(result).To(HaveLen(2)) + Expect(result[0]).To(ConsistOf(2, 4, 6, 8, 10)) + Expect(result[1]).To(ConsistOf(1, 3, 5, 7, 9, 11)) + }) + }) + + Describe("MostFrequent", func() { + It("returns zero value if no arguments are passed", func() { + Expect(slice.MostFrequent([]int{})).To(BeZero()) + }) + + It("returns the single item", func() { + Expect(slice.MostFrequent([]string{"123"})).To(Equal("123")) + }) + It("returns the item that appeared more times", func() { + Expect(slice.MostFrequent([]string{"1", "2", "1", "2", "3", "2"})).To(Equal("2")) + }) + }) + + Describe("Move", func() { + It("moves item to end of slice", func() { + Expect(slice.Move([]string{"1", "2", "3"}, 0, 2)).To(ConsistOf("2", "3", "1")) + }) + It("moves item to beginning of slice", func() { + Expect(slice.Move([]string{"1", "2", "3"}, 2, 0)).To(ConsistOf("3", "1", "2")) + }) + It("keeps item in same position if srcIndex == dstIndex", func() { + Expect(slice.Move([]string{"1", "2", "3"}, 1, 1)).To(ConsistOf("1", "2", "3")) + }) }) }) diff --git a/utils/strings.go b/utils/strings.go index c88c96b3..9fbe0d44 100644 --- a/utils/strings.go +++ b/utils/strings.go @@ -17,19 +17,6 @@ func NoArticle(name string) string { return name } -func InsertString(slice []string, value string, index int) []string { - return append(slice[:index], append([]string{value}, slice[index:]...)...) -} - -func RemoveString(slice []string, index int) []string { - return append(slice[:index], slice[index+1:]...) -} - -func MoveString(slice []string, srcIndex int, dstIndex int) []string { - value := slice[srcIndex] - return InsertString(RemoveString(slice, srcIndex), value, dstIndex) -} - func BreakUpStringSlice(items []string, chunkSize int) [][]string { numTracks := len(items) var chunks [][]string diff --git a/utils/strings_test.go b/utils/strings_test.go index 16599075..0983faa2 100644 --- a/utils/strings_test.go +++ b/utils/strings_test.go @@ -35,18 +35,6 @@ var _ = Describe("Strings", func() { }) }) - Describe("MoveString", func() { - It("moves item to end of slice", func() { - Expect(MoveString([]string{"1", "2", "3"}, 0, 2)).To(ConsistOf("2", "3", "1")) - }) - It("moves item to beginning of slice", func() { - Expect(MoveString([]string{"1", "2", "3"}, 2, 0)).To(ConsistOf("3", "1", "2")) - }) - It("keeps item in same position if srcIndex == dstIndex", func() { - Expect(MoveString([]string{"1", "2", "3"}, 1, 1)).To(ConsistOf("1", "2", "3")) - }) - }) - Describe("BreakUpStringSlice", func() { It("returns no chunks if slice is empty", func() { var slice []string