-
Notifications
You must be signed in to change notification settings - Fork 0
/
unmarshal.go
124 lines (102 loc) · 2.88 KB
/
unmarshal.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// SPDX-FileCopyrightText: 2020-2024 caixw
//
// SPDX-License-Identifier: MIT
package serialize
import (
"io/fs"
"os"
"path/filepath"
"github.com/issue9/localeutil"
"github.com/issue9/sliceutil"
"github.com/issue9/localeutil/message"
)
type UnmarshalFunc = func([]byte, any) error
// Search 根据文件名查找解码的方法
type Search = func(string) UnmarshalFunc
// Unmarshal 加载内容
func Unmarshal(data []byte, u UnmarshalFunc) (*message.Language, error) {
l := &message.Language{}
if err := u(data, l); err != nil {
return nil, err
}
return l, nil
}
func LoadFile(path string, u UnmarshalFunc) (*message.Language, error) {
return unmarshalFS(func() ([]byte, error) { return os.ReadFile(path) }, u)
}
func LoadFS(fsys fs.FS, name string, u UnmarshalFunc) (*message.Language, error) {
return unmarshalFS(func() ([]byte, error) { return fs.ReadFile(fsys, name) }, u)
}
func unmarshalFS(f func() ([]byte, error), u UnmarshalFunc) (*message.Language, error) {
data, err := f()
if err != nil {
return nil, err
}
return Unmarshal(data, u)
}
// LoadGlob 批量加载文件
//
// 相同语言 ID 的项会合并。
func LoadGlob(s Search, glob string) ([]*message.Language, error) {
matches, err := filepath.Glob(glob)
if err != nil {
return nil, err
}
langs := make([]*message.Language, 0, len(matches))
for _, match := range matches {
u := s(match)
if u == nil {
return nil, localeutil.Error("not found unmarshal for %s", match)
}
l, err := LoadFile(match, u)
if err != nil {
return nil, err
}
langs = append(langs, l)
}
return joinLanguages(langs), nil
}
// LoadFSGlob 批量加载文件
//
// 相同语言 ID 的项会合并。
func LoadFSGlob(s Search, glob string, fsys ...fs.FS) ([]*message.Language, error) {
langs := make([]*message.Language, 0, 10)
for _, f := range fsys {
matches, err := fs.Glob(f, glob)
if err != nil {
return nil, err
}
for _, match := range matches {
u := s(match)
if u == nil {
return nil, localeutil.Error("not found unmarshal for %s", match)
}
l, err := LoadFS(f, match, u)
if err != nil {
return nil, err
}
langs = append(langs, l)
}
}
return joinLanguages(langs), nil
}
func joinLanguages(langs []*message.Language) []*message.Language {
delIndexes := make([]int, 0, len(langs))
for index, lang := range langs {
// 该元素已经被标记为删除
if sliceutil.Exists(delIndexes, func(v int, _ int) bool { return index == v }) {
continue
}
// 找与 lang.ID 相同的元素索引
indexes := sliceutil.Indexes(langs, func(l *message.Language, i int) bool {
return l.ID == lang.ID && i != index
})
for _, i := range indexes {
lang.Join(langs[i])
}
delIndexes = append(delIndexes, indexes...)
}
return sliceutil.QuickDelete(langs, func(_ *message.Language, index int) bool {
return sliceutil.Exists(delIndexes, func(i int, _ int) bool { return i == index })
})
}