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]. // 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 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. // For [Album] where IsFull returns false, any variant other than [AlbumVariantCurrent] is undefined.
func (a *Album) Copy(variant int) *Album { func (a *Album) Copy(v *Album, variant int) bool {
if a == nil { if v == nil || a == nil || v == a {
return nil return false
} }
v := *a
if variant == AlbumVariantCurrent { if variant == AlbumVariantCurrent {
return &v *v = *a
return true
} }
if !a.IsFull() { if !a.IsFull() {
return nil return false
} }
switch variant { switch variant {
case AlbumVariantFull: case AlbumVariantFull:
break *v = *a
case AlbumVariantDetail: case AlbumVariantDetail:
a.Artists = nil *v = *a
v.Artists = nil
case AlbumVariantData: case AlbumVariantData:
a.Songs = nil *v = *a
v.Songs = nil
case AlbumVariantBase: case AlbumVariantBase:
a.Intro = "" *v = *a
a.Belong = "" v.Intro = ""
a.CoverDeURL = "" v.Belong = ""
a.Songs = nil v.CoverDeURL = ""
v.Songs = nil
default: default:
return nil return false
} }
return a return true
} }
// Enrich populates the remaining fields of a non-full [Album]. // Enrich populates the remaining fields of a non-full [Album].

View File

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

View File

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