treewide: copy to address

This saves the unnecessary extra copy.

Signed-off-by: Yonah <contrib@gensokyo.uk>
This commit is contained in:
Yonah 2025-09-18 23:37:09 +09:00
parent 0999ccd211
commit 30599306f1
Signed by: yonah
SSH Key Fingerprint: SHA256:vnQvK8+XXH9Tbni2AV1a/8qdVK/zPcXw52GM0ruQvwA
4 changed files with 70 additions and 56 deletions

View File

@ -62,40 +62,43 @@ func (a *Album) IsFull() bool { return a.Belong != "" && len(a.Songs) > 0 }
// Copy makes a copy of [Album].
// For an [Album] where the IsFull method returns true, Copy zeroes fields to convert the copy into other variants.
// For [Album] where IsFull returns false, any variant other than [AlbumVariantCurrent] is undefined.
func (a *Album) Copy(variant int) *Album {
if a == nil {
return nil
func (a *Album) Copy(v *Album, variant int) bool {
if v == nil || a == nil || v == a {
return false
}
v := *a
if variant == AlbumVariantCurrent {
return &v
*v = *a
return true
}
if !a.IsFull() {
return nil
return false
}
switch variant {
case AlbumVariantFull:
break
*v = *a
case AlbumVariantDetail:
a.Artists = nil
*v = *a
v.Artists = nil
case AlbumVariantData:
a.Songs = nil
*v = *a
v.Songs = nil
case AlbumVariantBase:
a.Intro = ""
a.Belong = ""
a.CoverDeURL = ""
a.Songs = nil
*v = *a
v.Intro = ""
v.Belong = ""
v.CoverDeURL = ""
v.Songs = nil
default:
return nil
return false
}
return a
return true
}
// Enrich populates the remaining fields of a non-full [Album].

View File

@ -33,24 +33,25 @@ func TestAlbum(t *testing.T) {
name string
a *Album
variant int
want *Album
want Album
wantOk bool
}{
{"nil", nil, AlbumVariantDetail, nil},
{"current", new(Album), AlbumVariantCurrent, new(Album)},
{"full guard", new(Album), AlbumVariantDetail, nil},
{"nil", nil, AlbumVariantDetail, Album{CID: -0xdeadbeef}, false},
{"current", new(Album), AlbumVariantCurrent, Album{}, true},
{"full guard", new(Album), AlbumVariantDetail, Album{CID: -0xdeadbeef}, false},
{"current full", &Album{
Belong: "\x00",
Songs: []AlbumSong{{}},
}, AlbumVariantCurrent, &Album{
}, AlbumVariantCurrent, Album{
Belong: "\x00",
Songs: []AlbumSong{{}},
}},
}, true},
{"oob", &Album{
Belong: "\x00",
Songs: []AlbumSong{{}},
}, 0xbad, nil},
}, 0xbad, Album{CID: -0xdeadbeef}, false},
{"full", &Album{
CID: 1030,
@ -64,7 +65,7 @@ func TestAlbum(t *testing.T) {
{CID: 125012, Name: "Speed of Light (Instrumental)", Artists: []string{"DJ Okawari"}},
},
Artists: []string{"塞壬唱片-MSR", "DJ Okawari"},
}, AlbumVariantFull, &Album{
}, AlbumVariantFull, Album{
CID: 1030,
Name: "Speed of Light",
Intro: "在无人告知方向的黑夜里,独自以光速探寻正确的道路。 \n无论看待世界是简单亦或是复杂大地和天空始终让开始与结束相连。 \n《Speed of Light》通过乐调铺陈的驰放与内敛感希望能为您呈现超脱于现实的惬意想象空间。 \n愿您掌心的小小地图一直指引着前路。像光一样前行如企鹅物流般永不停歇。",
@ -76,7 +77,7 @@ func TestAlbum(t *testing.T) {
{CID: 125012, Name: "Speed of Light (Instrumental)", Artists: []string{"DJ Okawari"}},
},
Artists: []string{"塞壬唱片-MSR", "DJ Okawari"},
}},
}, true},
{"detail", &Album{
CID: 1030,
@ -90,7 +91,7 @@ func TestAlbum(t *testing.T) {
{CID: 125012, Name: "Speed of Light (Instrumental)", Artists: []string{"DJ Okawari"}},
},
Artists: []string{"塞壬唱片-MSR", "DJ Okawari"},
}, AlbumVariantDetail, &Album{
}, AlbumVariantDetail, Album{
CID: 1030,
Name: "Speed of Light",
Intro: "在无人告知方向的黑夜里,独自以光速探寻正确的道路。 \n无论看待世界是简单亦或是复杂大地和天空始终让开始与结束相连。 \n《Speed of Light》通过乐调铺陈的驰放与内敛感希望能为您呈现超脱于现实的惬意想象空间。 \n愿您掌心的小小地图一直指引着前路。像光一样前行如企鹅物流般永不停歇。",
@ -101,7 +102,7 @@ func TestAlbum(t *testing.T) {
{CID: 880374, Name: "Speed of Light", Artists: []string{"塞壬唱片-MSR", "DJ Okawari"}},
{CID: 125012, Name: "Speed of Light (Instrumental)", Artists: []string{"DJ Okawari"}},
},
}},
}, true},
{"data", &Album{
CID: 1030,
@ -115,7 +116,7 @@ func TestAlbum(t *testing.T) {
{CID: 125012, Name: "Speed of Light (Instrumental)", Artists: []string{"DJ Okawari"}},
},
Artists: []string{"塞壬唱片-MSR", "DJ Okawari"},
}, AlbumVariantData, &Album{
}, AlbumVariantData, Album{
CID: 1030,
Name: "Speed of Light",
Intro: "在无人告知方向的黑夜里,独自以光速探寻正确的道路。 \n无论看待世界是简单亦或是复杂大地和天空始终让开始与结束相连。 \n《Speed of Light》通过乐调铺陈的驰放与内敛感希望能为您呈现超脱于现实的惬意想象空间。 \n愿您掌心的小小地图一直指引着前路。像光一样前行如企鹅物流般永不停歇。",
@ -123,7 +124,7 @@ func TestAlbum(t *testing.T) {
CoverDeURL: "https://web.hycdn.cn/siren/pic/20210322/0bf0d84e08b57acd2455b412224ba8e8.jpg",
CoverURL: "https://web.hycdn.cn/siren/pic/20210322/56cbcd1d0093d8ee8ee22bf6d68ab4a6.jpg",
Artists: []string{"塞壬唱片-MSR", "DJ Okawari"},
}},
}, true},
{"base", &Album{
CID: 1030,
@ -137,16 +138,20 @@ func TestAlbum(t *testing.T) {
{CID: 125012, Name: "Speed of Light (Instrumental)", Artists: []string{"DJ Okawari"}},
},
Artists: []string{"塞壬唱片-MSR", "DJ Okawari"},
}, AlbumVariantBase, &Album{
}, AlbumVariantBase, Album{
CID: 1030,
Name: "Speed of Light",
CoverURL: "https://web.hycdn.cn/siren/pic/20210322/56cbcd1d0093d8ee8ee22bf6d68ab4a6.jpg",
Artists: []string{"塞壬唱片-MSR", "DJ Okawari"},
}},
}, true},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if got := tc.a.Copy(tc.variant); !reflect.DeepEqual(got, tc.want) {
got := Album{CID: -0xdeadbeef}
if ok := tc.a.Copy(&got, tc.variant); ok != tc.wantOk {
t.Errorf("Copy: ok = %v, want %v", ok, tc.wantOk)
}
if !reflect.DeepEqual(got, tc.want) {
t.Errorf("Copy: %#v, want %#v", got, tc.want)
}
})

27
song.go
View File

@ -41,34 +41,35 @@ func (s *Song) IsFull() bool { return s.SourceURL != "" }
// Copy makes a copy of [Song].
// For a [Song] where the IsFull method returns true, Copy zeroes fields to convert the copy into other variants.
// For [Song] where IsFull returns false, any variant other than [SongVariantCurrent] is undefined.
func (s *Song) Copy(variant int) *Song {
if s == nil {
return nil
func (s *Song) Copy(v *Song, variant int) bool {
if v == nil || s == nil || v == s {
return false
}
v := *s
if variant == SongVariantCurrent {
return &v
*v = *s
return true
}
if !s.IsFull() {
return nil
return false
}
switch variant {
case SongVariantFull:
break
*v = *s
case SongVariantBase:
s.SourceURL = ""
s.LyricURL = ""
s.MvURL = ""
s.MvCoverURL = ""
*v = *s
v.SourceURL = ""
v.LyricURL = ""
v.MvURL = ""
v.MvCoverURL = ""
default:
return nil
return false
}
return s
return true
}
// Enrich populates the remaining fields of a non-full [Song].

View File

@ -28,21 +28,22 @@ func TestSong(t *testing.T) {
name string
a *Song
variant int
want *Song
want Song
wantOk bool
}{
{"nil", nil, SongVariantBase, nil},
{"current", new(Song), SongVariantCurrent, new(Song)},
{"full guard", new(Song), SongVariantFull, nil},
{"nil", nil, SongVariantBase, Song{CID: -0xdeadbeef}, false},
{"current", new(Song), SongVariantCurrent, Song{}, true},
{"full guard", new(Song), SongVariantFull, Song{CID: -0xdeadbeef}, false},
{"current full", &Song{
SourceURL: "\x00",
}, SongVariantCurrent, &Song{
}, SongVariantCurrent, Song{
SourceURL: "\x00",
}},
}, true},
{"oob", &Song{
SourceURL: "\x00",
}, 0xbad, nil},
}, 0xbad, Song{CID: -0xdeadbeef}, false},
{"full", &Song{
CID: 48794,
@ -51,14 +52,14 @@ func TestSong(t *testing.T) {
SourceURL: "https://res01.hycdn.cn/04ce5de54bb52eb85008644d541d40fa/68CA0442/siren/audio/20240709/a7f650238eaefc9c30a9627d7f78d819.wav",
LyricURL: "https://web.hycdn.cn/siren/lyric/20240709/4a10c70629b68a187fdbef4a27bd32d8.lrc",
Artists: []string{"塞壬唱片-MSR"},
}, SongVariantFull, &Song{
}, SongVariantFull, Song{
CID: 48794,
Name: "Warm and Small Light",
AlbumCID: 6660,
SourceURL: "https://res01.hycdn.cn/04ce5de54bb52eb85008644d541d40fa/68CA0442/siren/audio/20240709/a7f650238eaefc9c30a9627d7f78d819.wav",
LyricURL: "https://web.hycdn.cn/siren/lyric/20240709/4a10c70629b68a187fdbef4a27bd32d8.lrc",
Artists: []string{"塞壬唱片-MSR"},
}},
}, true},
{"base", &Song{
CID: 48794,
@ -67,16 +68,20 @@ func TestSong(t *testing.T) {
SourceURL: "https://res01.hycdn.cn/04ce5de54bb52eb85008644d541d40fa/68CA0442/siren/audio/20240709/a7f650238eaefc9c30a9627d7f78d819.wav",
LyricURL: "https://web.hycdn.cn/siren/lyric/20240709/4a10c70629b68a187fdbef4a27bd32d8.lrc",
Artists: []string{"塞壬唱片-MSR"},
}, SongVariantBase, &Song{
}, SongVariantBase, Song{
CID: 48794,
Name: "Warm and Small Light",
AlbumCID: 6660,
Artists: []string{"塞壬唱片-MSR"},
}},
}, true},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if got := tc.a.Copy(tc.variant); !reflect.DeepEqual(got, tc.want) {
got := Song{CID: -0xdeadbeef}
if ok := tc.a.Copy(&got, tc.variant); ok != tc.wantOk {
t.Errorf("Copy: ok = %v, want %v", ok, tc.wantOk)
}
if !reflect.DeepEqual(got, tc.want) {
t.Errorf("Copy: %#v, want %#v", got, tc.want)
}
})