1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
16
17 package index
18
19 import (
20 "bytes"
21 "errors"
22
23 "perkeep.org/internal/magic"
24 "perkeep.org/pkg/blob"
25 "perkeep.org/pkg/schema"
26 )
27
28 type BlobSniffer struct {
29 br blob.Ref
30
31 contents []byte
32 written int64
33 meta *schema.Blob
34 mimeType string
35 camliType schema.CamliType
36 }
37
38 func NewBlobSniffer(ref blob.Ref) *BlobSniffer {
39 if !ref.Valid() {
40 panic("invalid ref")
41 }
42 return &BlobSniffer{br: ref}
43 }
44
45 func (sn *BlobSniffer) SchemaBlob() (meta *schema.Blob, ok bool) {
46 return sn.meta, sn.meta != nil
47 }
48
49 func (sn *BlobSniffer) Write(d []byte) (int, error) {
50 if !sn.br.Valid() {
51 panic("write on sniffer with invalid blobref")
52 }
53 sn.written += int64(len(d))
54 if len(sn.contents) < schema.MaxSchemaBlobSize {
55 n := schema.MaxSchemaBlobSize - len(sn.contents)
56 if len(d) < n {
57 n = len(d)
58 }
59 sn.contents = append(sn.contents, d[:n]...)
60 }
61 return len(d), nil
62 }
63
64
65
66
67 func (sn *BlobSniffer) Size() int64 {
68 return sn.written
69 }
70
71
72
73 func (sn *BlobSniffer) IsTruncated() bool {
74 return sn.written > schema.MaxSchemaBlobSize
75 }
76
77
78 func (sn *BlobSniffer) Body() ([]byte, error) {
79 if sn.IsTruncated() {
80 return nil, errors.New("index.Body: was truncated")
81 }
82 return sn.contents, nil
83 }
84
85
86
87
88 func (sn *BlobSniffer) MIMEType() string { return sn.mimeType }
89
90 func (sn *BlobSniffer) CamliType() schema.CamliType { return sn.camliType }
91
92 func (sn *BlobSniffer) Parse() {
93 if sn.bufferIsCamliJSON() {
94 sn.camliType = sn.meta.Type()
95 sn.mimeType = "application/json; camliType=" + string(sn.camliType)
96 } else {
97 sn.mimeType = magic.MIMEType(sn.contents)
98 }
99 }
100
101 func (sn *BlobSniffer) bufferIsCamliJSON() bool {
102 buf := sn.contents
103 if !schema.LikelySchemaBlob(buf) {
104 return false
105 }
106 blob, err := schema.BlobFromReader(sn.br, bytes.NewReader(buf))
107 if err != nil {
108 return false
109 }
110 sn.meta = blob
111 return true
112 }