aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--account.go2
-rw-r--r--container.go11
-rw-r--r--headers.go27
3 files changed, 37 insertions, 3 deletions
diff --git a/account.go b/account.go
index 4438ce8..f4e8c07 100644
--- a/account.go
+++ b/account.go
@@ -117,6 +117,7 @@ func (a *Account) Invalidate() {
//
//A successful POST request implies Invalidate() since it may change metadata.
func (a *Account) Update(headers AccountHeaders, opts *RequestOptions) error {
+ ensureInitializedByReflection(headers)
_, err := Request{
Method: "POST",
Headers: headers.ToHTTP(),
@@ -137,6 +138,7 @@ func (a *Account) Update(headers AccountHeaders, opts *RequestOptions) error {
//
//A successful PUT request implies Invalidate() since it may change metadata.
func (a *Account) Create(headers AccountHeaders, opts *RequestOptions) error {
+ ensureInitializedByReflection(headers)
_, err := Request{
Method: "PUT",
Headers: headers.ToHTTP(),
diff --git a/container.go b/container.go
index e3b95d8..cfc0eab 100644
--- a/container.go
+++ b/container.go
@@ -96,6 +96,7 @@ func (c *Container) Headers() (ContainerHeaders, error) {
//
//A successful POST request implies Invalidate() since it may change metadata.
func (c *Container) Update(headers ContainerHeaders, opts *RequestOptions) error {
+ ensureInitializedByReflection(headers)
_, err := Request{
Method: "POST",
ContainerName: c.name,
@@ -116,6 +117,7 @@ func (c *Container) Update(headers ContainerHeaders, opts *RequestOptions) error
//
//A successful PUT request implies Invalidate() since it may change metadata.
func (c *Container) Create(headers ContainerHeaders, opts *RequestOptions) error {
+ ensureInitializedByReflection(headers)
_, err := Request{
Method: "PUT",
ContainerName: c.name,
@@ -137,7 +139,14 @@ func (c *Container) Create(headers ContainerHeaders, opts *RequestOptions) error
//This operation fails with http.StatusNotFound if the container does not exist.
//
//A successful DELETE request implies Invalidate().
-func (c *Container) Delete(headers ContainerHeaders, opts *RequestOptions) error {
+func (c *Container) Delete(headers *ContainerHeaders, opts *RequestOptions) error {
+ if headers == nil {
+ h := NewContainerHeaders()
+ headers = &h
+ } else {
+ ensureInitializedByReflection(*headers)
+ }
+
_, err := Request{
Method: "DELETE",
ContainerName: c.name,
diff --git a/headers.go b/headers.go
index 44d0607..2d81ddf 100644
--- a/headers.go
+++ b/headers.go
@@ -19,6 +19,7 @@
package schwift
import (
+ "fmt"
"reflect"
"github.com/majewsky/schwift/headers"
@@ -29,6 +30,9 @@ import (
//request on the account, and will be sent by a PUT or POST request. The other
//attributes allow type-safe access to well-known headers, as noted in the tags
//next to each field.
+//
+//Follow the link on the Headers attribute for the documentation of the Get(),
+//Set(), Del(), Clear() methods on this type.
type AccountHeaders struct {
headers.Headers
BytesUsed headers.Uint64Readonly `schwift:"X-Account-Bytes-Used"`
@@ -39,14 +43,18 @@ type AccountHeaders struct {
TempURLKey headers.String `schwift:"X-Account-Meta-Temp-URL-Key"`
TempURLKey2 headers.String `schwift:"X-Account-Meta-Temp-URL-Key-2"`
//forbid initialization as struct literal (must use NewAccountHeaders)
- private struct{}
+ initialized bool
}
//NewAccountHeaders prepares a new AccountHeaders instance.
+//
+//WARNING: Always use this function to construct AccountHeaders instances.
+//Failure to do so will result in uncontrolled crashes!
func NewAccountHeaders() AccountHeaders {
var ah AccountHeaders
ah.Headers = make(headers.Headers)
initializeByReflection(&ah)
+ ah.initialized = true
return ah
}
@@ -64,19 +72,26 @@ func (ah AccountHeaders) Validate() error {
//request on the container, and will be sent by a PUT or POST request. The
//other attributes allow type-safe access to well-known headers, as noted in
//the tags next to each field.
+//
+//Follow the link on the Headers attribute for the documentation of the Get(),
+//Set(), Del(), Clear() methods on this type.
type ContainerHeaders struct {
headers.Headers
Metadata headers.Metadata `schwift:"X-Container-Meta-"`
//TODO map well-known headers
//forbid initialization as struct literal (must use NewContainerHeaders)
- private struct{}
+ initialized bool
}
//NewContainerHeaders prepares a new ContainerHeaders instance.
+//
+//WARNING: Always use this function to construct ContainerHeaders instances.
+//Failure to do so will result in uncontrolled crashes!
func NewContainerHeaders() ContainerHeaders {
var ch ContainerHeaders
ch.Headers = make(headers.Headers)
initializeByReflection(&ch)
+ ch.initialized = true
return ch
}
@@ -122,6 +137,14 @@ func validateByReflection(value interface{}) error {
})
}
+func ensureInitializedByReflection(value interface{}) {
+ initialized := reflect.ValueOf(value).FieldByName("initialized").Bool()
+ if !initialized {
+ msg := "values of type %T MUST be initialized with the corresponding New...() function"
+ panic(fmt.Sprintf(msg, value, value))
+ }
+}
+
func foreachTaggedField(value interface{}, callback func(fieldPtr interface{}, info fieldInfo) error) error {
rv := reflect.ValueOf(value).Elem()