/
magic.go
100 lines (92 loc) · 1.98 KB
/
magic.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
package indexed
import (
"encoding/binary"
"errors"
"io"
"log"
"os"
"regexp"
"strings"
"github.com/nimezhu/netio"
)
const BIGWIG_MAGIC = 0x888FFC26
const BIGBED_MAGIC = 0x8789F2EB
const TWOBIT_MAGIC = 0x1A412743
const HIC_MAGIC = 0x00434948
var GZIP_MAGIC = []byte("\x1f\x8b")
const BIGSIZE = 100000000 //100Mb is bigbedLarge
func MagicReadSeeker(f io.ReadSeeker) (string, error) {
p := make([]byte, 4)
f.Seek(0, 0)
defer f.Seek(0, 0)
l, err := f.Read(p)
if p[0] == GZIP_MAGIC[0] && p[1] == GZIP_MAGIC[1] {
return "gzip", nil
}
if err != nil {
log.Println(l, err)
}
n := binary.LittleEndian.Uint32(p)
switch n {
case BIGBED_MAGIC:
return "bigbed", nil
case BIGWIG_MAGIC:
return "bigwig", nil
case HIC_MAGIC:
return "hic", nil
case TWOBIT_MAGIC:
return "twobit", nil
}
return "unknown", errors.New("unknown format")
}
func Magic(uri string) (string, error) {
/*TODO UPDATE CUSTOMIZED FORMAT
if ok, _ := regexp.MatchString("^binindex:", uri); ok {
return "binindex", nil
}
if _, err := os.Stat(filepath.Join(filepath.Dir(uri), "images")); err == nil {
if _, err := os.Stat(uri + ".tbi"); err == nil {
return "image", err
}
}
*/
/* customized format Interface */
/* _format_:[[format]]:[[uri]] */
if ok, _ := regexp.MatchString("_format_:", uri); ok {
a := strings.Split(uri, ":")
if len(a) >= 3 {
return a[1], nil
}
}
if _, err := os.Stat(uri + ".tbi"); err == nil {
return "tabix", err
}
f, err := netio.NewReadSeeker(uri)
if err != nil {
return "unknown", err
}
size, err := netio.Size(uri)
if err != nil {
return "unknown", err
}
p := make([]byte, 4)
f.Read(p)
if p[0] == GZIP_MAGIC[0] && p[1] == GZIP_MAGIC[1] {
return "gzip", nil
}
n := binary.LittleEndian.Uint32(p)
switch n {
case BIGBED_MAGIC:
if size > BIGSIZE {
return "bigbedLarge", nil
}
return "bigbed", nil
case BIGWIG_MAGIC:
return "bigwig", nil
case HIC_MAGIC:
return "hic", nil
case TWOBIT_MAGIC:
return "twobit", nil
}
return "unknown", nil
}