-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmediatype.go
127 lines (105 loc) · 2.75 KB
/
mediatype.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
125
126
127
package lime
import (
"encoding/json"
"errors"
"fmt"
"strings"
)
const (
MediaTypeText = "text"
MediaTypeApplication = "application"
MediaTypeImage = "image"
MediaTypeAudio = "audio"
MediaTypeVideo = "video"
)
// MediaType represents a MIME type.
type MediaType struct {
// Type is the top-level type identifier.
// The valid values are text, application, image, audio and video.
Type string
// Subtype is the MIME subtype.
Subtype string
// Suffix is the MIME suffix.
Suffix string
}
// IsJson indicates if the MIME represents a JSON type.
func (m MediaType) IsJson() bool {
return m.Suffix == "json"
}
func (m MediaType) String() string {
if m == (MediaType{}) {
return ""
}
v := fmt.Sprintf("%v/%v", m.Type, m.Subtype)
if m.Suffix != "" {
return fmt.Sprintf("%v+%v", v, m.Suffix)
}
return v
}
func ParseMediaType(s string) (MediaType, error) {
var suffix string
values := strings.Split(s, "+")
if len(values) > 1 {
suffix = values[1]
}
values = strings.Split(values[0], "/")
if len(values) == 1 {
return MediaType{}, errors.New("invalid media type")
}
return MediaType{values[0], values[1], suffix}, nil
}
func (m MediaType) MarshalText() ([]byte, error) {
return []byte(m.String()), nil
}
func (m *MediaType) UnmarshalText(text []byte) error {
mediaType, err := ParseMediaType(string(text))
if err != nil {
return err
}
*m = mediaType
return nil
}
// Unexported to avoid changing
var mediaTypeApplicationJson = MediaType{MediaTypeApplication, "json", ""}
var mediaTypeTextPlain = MediaType{MediaTypeText, "plain", ""}
var documentFactories = map[MediaType]func() Document{}
func MediaTypeTextPlain() MediaType {
return mediaTypeTextPlain
}
func MediaTypeApplicationJson() MediaType {
return mediaTypeApplicationJson
}
// RegisterDocumentFactory allow the registration of new Document types, which allow these types to be discovered
// for the envelope deserialization process.
func RegisterDocumentFactory(f func() Document) {
d := f()
documentFactories[d.MediaType()] = f
}
func GetDocumentFactory(t MediaType) (func() Document, error) {
// Check for a specific document factory for the media type
factory, ok := documentFactories[t]
if !ok {
// Use the default ones
if t.IsJson() {
factory = documentFactories[mediaTypeApplicationJson]
} else {
factory = documentFactories[mediaTypeTextPlain]
}
}
if factory == nil {
return nil, fmt.Errorf("no document factory found for media type %v", t)
}
return factory, nil
}
func UnmarshalDocument(d *json.RawMessage, t MediaType) (Document, error) {
factory, err := GetDocumentFactory(t)
if err != nil {
return nil, err
}
document := factory()
err = json.Unmarshal(*d, &document)
if err != nil {
return nil, err
}
return document, nil
}