Skip to content

Commit ae6c636

Browse files
committed
Rearranging KFX code a bit to make it easier to follow.
1 parent d802f9d commit ae6c636

File tree

1 file changed

+74
-57
lines changed

1 file changed

+74
-57
lines changed

thumbs/kfx/reader.go

Lines changed: 74 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -103,19 +103,12 @@ func (r *Reader) extractThumbnail(data []byte) error {
103103
return fmt.Errorf("unable to read KFX document symbols: %w", err)
104104
}
105105

106-
type entity struct {
107-
id uint32
108-
idType uint32
109-
data []byte
110-
}
111-
entities := make(map[uint32][]*entity)
106+
entities := newEntitySet(docSymbols)
112107

113108
indexTabReader := bytes.NewReader(data[contInfo.IndexTabOffset : contInfo.IndexTabOffset+contInfo.IndexTabLength])
114109
tabEntry := struct {
115-
NumID uint32
116-
NumType uint32
117-
Offset uint64
118-
Size uint64
110+
NumID, NumType uint32
111+
Offset, Size uint64
119112
}{}
120113

121114
for {
@@ -156,24 +149,17 @@ func (r *Reader) extractThumbnail(data []byte) error {
156149
if err := entyInfo.validate(); err != nil {
157150
return err
158151
}
159-
160-
entities[tabEntry.NumType] = append(entities[tabEntry.NumType],
161-
&entity{
162-
id: tabEntry.NumID,
163-
idType: tabEntry.NumType,
164-
data: enty[entyHeader.Size:],
165-
})
152+
entities.addEntity(tabEntry.NumID, tabEntry.NumType, enty[entyHeader.Size:])
166153
}
167154

168-
meta, exists := entities[symBookMetadata]
169-
if !exists {
155+
metas := entities.getAllOfType(symBookMetadata)
156+
if len(metas) == 0 {
170157
// NOTE: KFX input plugin expects case like this and attempts to get to
171-
// $258 directly, processing it differently I am ignoring this for now
172-
// as I never seen case like this.
158+
// $258 (Metadata) directly, processing it differently in this case. I
159+
// am ignoring this for now as I never seen case like this.
173160
return errors.New("no book metadata found")
174-
}
175-
if len(meta) != 1 {
176-
return fmt.Errorf("ambiguous metadata, expected single book metadata entity, got %d", len(meta))
161+
} else if len(metas) != 1 {
162+
return fmt.Errorf("ambiguous metadata, expected single book metadata entity, got %d", len(metas))
177163
}
178164

179165
type (
@@ -190,7 +176,7 @@ func (r *Reader) extractThumbnail(data []byte) error {
190176
}
191177
)
192178
var bmd bookMetadata
193-
if err := decodeData(lstProlog, meta[0].data, &bmd); err != nil {
179+
if err := decodeData(lstProlog, metas[0].data, &bmd); err != nil {
194180
return err
195181
}
196182
if index := slices.IndexFunc(bmd.CategorizedMetadata, func(p properties) bool {
@@ -221,21 +207,9 @@ func (r *Reader) extractThumbnail(data []byte) error {
221207
return nil
222208
}
223209

224-
eres, exists := entities[symExternalResource]
225-
if !exists {
226-
return errors.New("no external resources found")
227-
}
228-
id, ok := docSymbols.FindByName(r.cover)
229-
if !ok {
230-
return errors.New("cover image name not found in the symbol table")
231-
}
232-
id -= ion.V1SystemSymbolTable.MaxID()
233-
234-
var index int
235-
if index = slices.IndexFunc(eres, func(e *entity) bool {
236-
return uint64(e.id) == id
237-
}); index == -1 {
238-
return errors.New("cover image id not found in the external resources")
210+
coverRes, err := entities.getByName(r.cover, symExternalResource)
211+
if err != nil {
212+
return fmt.Errorf("unable to get cover image entity: %w", err)
239213
}
240214

241215
c := struct {
@@ -246,29 +220,17 @@ func (r *Reader) extractThumbnail(data []byte) error {
246220
// Height int `ion:"$423"`
247221
// Mime string `ion:"$162"`
248222
}{}
249-
250-
if err := decodeData(lstProlog, eres[index].data, &c); err != nil {
223+
if err := decodeData(lstProlog, coverRes.data, &c); err != nil {
251224
return err
252225
}
253226

254-
imgDataID, ok := docSymbols.FindByName(c.Location)
255-
if !ok {
256-
return errors.New("cover image location not found in the symbol table")
257-
}
258-
imgDataID -= ion.V1SystemSymbolTable.MaxID()
259-
260-
media, exists := entities[symRawMedia]
261-
if !exists {
262-
return errors.New("no raw media fragments found in a book")
263-
}
264-
if index = slices.IndexFunc(media, func(e *entity) bool {
265-
return uint64(e.id) == imgDataID
266-
}); index == -1 {
267-
return errors.New("cover image raw media not found in the external resources")
227+
coverImage, err := entities.getByName(c.Location, symRawMedia)
228+
if err != nil {
229+
return fmt.Errorf("unable to get cover image data: %w", err)
268230
}
269231

270232
var img image.Image
271-
if img, _, err = image.Decode(bytes.NewReader(media[index].data)); err != nil {
233+
if img, _, err = image.Decode(bytes.NewReader(coverImage.data)); err != nil {
272234
return fmt.Errorf("unable to decode extracted cover: %w", err)
273235
}
274236
imgthumb := imaging.Thumbnail(img, r.width, r.height, imaging.Lanczos)
@@ -381,3 +343,58 @@ func (e *entityInfo) validate() error {
381343
}
382344
return nil
383345
}
346+
347+
type (
348+
entity struct {
349+
id, idType uint32
350+
data []byte
351+
}
352+
entitySet struct {
353+
st ion.SymbolTable
354+
fragments map[uint32][]*entity
355+
}
356+
)
357+
358+
func newEntitySet(st ion.SymbolTable) *entitySet {
359+
return &entitySet{
360+
st: st,
361+
fragments: make(map[uint32][]*entity),
362+
}
363+
}
364+
365+
func (s *entitySet) addEntity(id, idType uint32, data []byte) {
366+
s.fragments[idType] = append(s.fragments[idType],
367+
&entity{
368+
id: id,
369+
idType: idType,
370+
data: data,
371+
})
372+
}
373+
374+
func (s *entitySet) getAllOfType(idType uint32) []*entity {
375+
entities, exists := s.fragments[idType]
376+
if !exists {
377+
return nil
378+
}
379+
return entities
380+
}
381+
382+
func (s *entitySet) getByName(name string, idType uint32) (*entity, error) {
383+
entities, exists := s.fragments[idType]
384+
if !exists {
385+
return nil, fmt.Errorf("no entities of type '%d' found", idType)
386+
}
387+
id, ok := s.st.FindByName(name)
388+
if !ok {
389+
return nil, fmt.Errorf("symbol '%s' not found in the symbol table", name)
390+
}
391+
id -= ion.V1SystemSymbolTable.MaxID()
392+
393+
var index int
394+
if index = slices.IndexFunc(entities, func(e *entity) bool {
395+
return uint64(e.id) == id
396+
}); index == -1 {
397+
return nil, fmt.Errorf("entity fragment '%s' of type '%d' not found", name, idType)
398+
}
399+
return entities[index], nil
400+
}

0 commit comments

Comments
 (0)