forked from rackspace/gophercloud
-
Notifications
You must be signed in to change notification settings - Fork 0
/
results.go
162 lines (141 loc) · 4.32 KB
/
results.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package objects
import (
"fmt"
"io"
"io/ioutil"
"strings"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
"github.com/mitchellh/mapstructure"
)
// Object is a structure that holds information related to a storage object.
type Object struct {
Bytes int `json:"bytes" mapstructure:"bytes"`
ContentType string `json:"content_type" mapstructure:"content_type"`
Hash string `json:"hash" mapstructure:"hash"`
LastModified string `json:"last_modified" mapstructure:"last_modified"`
Name string `json:"name" mapstructure:"name"`
}
// ObjectPage is a single page of objects that is returned from a call to the
// List function.
type ObjectPage struct {
pagination.MarkerPageBase
}
// IsEmpty returns true if a ListResult contains no object names.
func (r ObjectPage) IsEmpty() (bool, error) {
names, err := ExtractNames(r)
if err != nil {
return true, err
}
return len(names) == 0, nil
}
// LastMarker returns the last object name in a ListResult.
func (r ObjectPage) LastMarker() (string, error) {
names, err := ExtractNames(r)
if err != nil {
return "", err
}
if len(names) == 0 {
return "", nil
}
return names[len(names)-1], nil
}
// ExtractInfo is a function that takes a page of objects and returns their full information.
func ExtractInfo(page pagination.Page) ([]Object, error) {
untyped := page.(ObjectPage).Body.([]interface{})
results := make([]Object, len(untyped))
for index, each := range untyped {
object := each.(map[string]interface{})
err := mapstructure.Decode(object, &results[index])
if err != nil {
return results, err
}
}
return results, nil
}
// ExtractNames is a function that takes a page of objects and returns only their names.
func ExtractNames(page pagination.Page) ([]string, error) {
casted := page.(ObjectPage)
ct := casted.Header.Get("Content-Type")
switch {
case strings.HasPrefix(ct, "application/json"):
parsed, err := ExtractInfo(page)
if err != nil {
return nil, err
}
names := make([]string, 0, len(parsed))
for _, object := range parsed {
names = append(names, object.Name)
}
return names, nil
case strings.HasPrefix(ct, "text/plain"):
names := make([]string, 0, 50)
body := string(page.(ObjectPage).Body.([]uint8))
for _, name := range strings.Split(body, "\n") {
if len(name) > 0 {
names = append(names, name)
}
}
return names, nil
case strings.HasPrefix(ct, "text/html"):
return []string{}, nil
default:
return nil, fmt.Errorf("Cannot extract names from response with content-type: [%s]", ct)
}
}
// DownloadResult is a *http.Response that is returned from a call to the Download function.
type DownloadResult struct {
gophercloud.HeaderResult
Body io.ReadCloser
}
// ExtractContent is a function that takes a DownloadResult's io.Reader body
// and reads all available data into a slice of bytes. Please be aware that due
// the nature of io.Reader is forward-only - meaning that it can only be read
// once and not rewound. You can recreate a reader from the output of this
// function by using bytes.NewReader(downloadBytes)
func (dr DownloadResult) ExtractContent() ([]byte, error) {
if dr.Err != nil {
return nil, dr.Err
}
body, err := ioutil.ReadAll(dr.Body)
if err != nil {
return nil, err
}
dr.Body.Close()
return body, nil
}
// GetResult is a *http.Response that is returned from a call to the Get function.
type GetResult struct {
gophercloud.HeaderResult
}
// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
// and returns the custom metadata associated with the object.
func (gr GetResult) ExtractMetadata() (map[string]string, error) {
if gr.Err != nil {
return nil, gr.Err
}
metadata := make(map[string]string)
for k, v := range gr.Header {
if strings.HasPrefix(k, "X-Object-Meta-") {
key := strings.TrimPrefix(k, "X-Object-Meta-")
metadata[key] = v[0]
}
}
return metadata, nil
}
// CreateResult represents the result of a create operation.
type CreateResult struct {
gophercloud.HeaderResult
}
// UpdateResult represents the result of an update operation.
type UpdateResult struct {
gophercloud.HeaderResult
}
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
gophercloud.HeaderResult
}
// CopyResult represents the result of a copy operation.
type CopyResult struct {
gophercloud.HeaderResult
}