This repository has been archived by the owner on Dec 29, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 16
/
unmarshal.go
122 lines (112 loc) · 3.12 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
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bigtiff
import (
"fmt"
"log"
"reflect"
"github.com/google/tiff"
)
func UnmarshalSubIFDs(ifd tiff.IFD, br tiff.BReader, tsp tiff.TagSpace, out interface{}) error {
if br == nil {
return fmt.Errorf("bigtiff: UnmarshalSubIFDs: no BReader available")
}
if len(ifd.Fields()) == 0 {
return fmt.Errorf("bigtiff: UnmarshalSubIFDs: ifd has no fields")
}
v := reflect.ValueOf(out).Elem()
structType := v.Type()
for i := 0; i < v.NumField(); i++ {
stField := structType.Field(i)
sTag := tiff.ParseTiffStructTag(stField.Tag.Get("tiff"))
if sTag == nil || sTag.Type != "subifd" {
continue
}
vf := v.Field(i)
vft := vf.Type()
vftk := vft.Kind()
if vftk != reflect.Ptr && vftk != reflect.Struct {
log.Printf("bigtiff: UnmarshalSubIFDs: using a tiff SubIFD struct tag is only supported for structs (not a %v)\n", vftk)
continue
}
siTag := tiff.ParseTiffSubIFDStructTag(sTag.Data)
if siTag == nil {
log.Printf("bigtiff: UnmarshalSubIFDs: skipping struct field %q due to malformed tiff subifd struct tag (%q).\n", stField.Name, sTag.Data)
continue
}
if siTag.Tag == nil {
log.Printf("bigtiff: UnmarshalSubIFDs: skipping struct field %q due to missing \"tag\" key in tiff subifd struct tag.\n", stField.Name)
continue
}
if !ifd.HasField(*siTag.Tag) {
// Default values do not work here. We have to simply skip it.
continue
}
ifdField := ifd.GetField(*siTag.Tag)
ifdFT := ifdField.Type()
fvBytes := ifdField.Value().Bytes()
fvBo := ifdField.Value().Order()
if ifdField.Count() == 0 {
continue
}
var offsets []uint64
switch ifdFT.ReflectType().Kind() {
case reflect.Uint32:
offsets = make([]uint64, ifdField.Count())
for i := range offsets {
offsets[i] = uint64(fvBo.Uint32(fvBytes))
fvBytes = fvBytes[4:]
}
case reflect.Uint64:
offsets = make([]uint64, ifdField.Count())
for i := range offsets {
offsets[i] = fvBo.Uint64(fvBytes)
fvBytes = fvBytes[8:]
}
default:
continue
}
off := offsets[0]
if siTag.Index != nil {
if *siTag.Index >= len(offsets) || *siTag.Index < 0 {
// log a warning
continue
}
off = offsets[*siTag.Index]
}
if tsp == nil {
if siTag.TagSpace != nil {
newSpace := tiff.GetTagSpace(*siTag.TagSpace)
if newSpace != nil {
tsp = newSpace
}
}
if tsp == nil {
tsp = tiff.DefaultTagSpace
}
}
subIFD, err := ParseIFD(br, uint64(off), tsp, nil)
if err != nil {
return err
}
switch vftk {
case reflect.Ptr:
// We do not support recursive unmarshaling when
// the field points back to the enclosing struct.
if vf.Elem() != v && vft.Elem().Kind() == reflect.Struct {
newStruct := reflect.New(vft.Elem())
if err := tiff.UnmarshalIFD(subIFD, newStruct.Interface()); err != nil {
return err
}
vf.Set(newStruct)
}
case reflect.Struct:
embStructPtr := v.Field(i).Addr().Interface()
if err := tiff.UnmarshalIFD(subIFD, embStructPtr); err != nil {
return err
}
}
}
return nil
}