More specific types for ObjectStorage response object fields (#74)

* more accurate types for objectstorage response object fields (e.g. ContentLength: string -> in64)

* containers unit tests for new field types

* more specific types for accounts headers fields

* update accounts unit tests

* download header unmarshal method and unit test

* object results unmarshal methods
diff --git a/openstack/objectstorage/v1/accounts/results.go b/openstack/objectstorage/v1/accounts/results.go
index f9e5fcd..216414b 100644
--- a/openstack/objectstorage/v1/accounts/results.go
+++ b/openstack/objectstorage/v1/accounts/results.go
@@ -1,6 +1,9 @@
 package accounts
 
 import (
+	"encoding/json"
+	"fmt"
+	"strconv"
 	"strings"
 
 	"github.com/gophercloud/gophercloud"
@@ -13,10 +16,36 @@
 
 // UpdateHeader represents the headers returned in the response from an Update request.
 type UpdateHeader struct {
-	ContentLength string                  `json:"Content-Length"`
+	ContentLength int64                   `json:"-"`
 	ContentType   string                  `json:"Content-Type"`
-	Date          gophercloud.JSONRFC1123 `json:"Date"`
 	TransID       string                  `json:"X-Trans-Id"`
+	Date          gophercloud.JSONRFC1123 `json:"Date"`
+}
+
+func (h *UpdateHeader) UnmarshalJSON(b []byte) error {
+	type tmp UpdateHeader
+	var updateHeader *struct {
+		tmp
+		ContentLength string `json:"Content-Length"`
+	}
+	err := json.Unmarshal(b, &updateHeader)
+	if err != nil {
+		return err
+	}
+
+	*h = UpdateHeader(updateHeader.tmp)
+
+	switch updateHeader.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(updateHeader.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
 }
 
 // Extract will return a struct of headers returned from a call to Get. To obtain
@@ -29,15 +58,75 @@
 
 // GetHeader represents the headers returned in the response from a Get request.
 type GetHeader struct {
-	BytesUsed      string                  `json:"X-Account-Bytes-Used"`
-	ContainerCount string                  `json:"X-Account-Container-Count"`
-	ContentLength  string                  `json:"Content-Length"`
+	BytesUsed      int64                   `json:"-"`
+	ContainerCount int64                   `json:"-"`
+	ContentLength  int64                   `json:"-"`
+	ObjectCount    int64                   `json:"-"`
 	ContentType    string                  `json:"Content-Type"`
-	Date           gophercloud.JSONRFC1123 `json:"Date"`
-	ObjectCount    string                  `json:"X-Account-Object-Count"`
 	TransID        string                  `json:"X-Trans-Id"`
 	TempURLKey     string                  `json:"X-Account-Meta-Temp-URL-Key"`
 	TempURLKey2    string                  `json:"X-Account-Meta-Temp-URL-Key-2"`
+	Date           gophercloud.JSONRFC1123 `json:"Date"`
+}
+
+func (h *GetHeader) UnmarshalJSON(b []byte) error {
+	type tmp GetHeader
+	var getHeader *struct {
+		tmp
+		BytesUsed      string `json:"X-Account-Bytes-Used"`
+		ContentLength  string `json:"Content-Length"`
+		ContainerCount string `json:"X-Account-Container-Count"`
+		ObjectCount    string `json:"X-Account-Object-Count"`
+	}
+	err := json.Unmarshal(b, &getHeader)
+	if err != nil {
+		return err
+	}
+
+	*h = GetHeader(getHeader.tmp)
+
+	switch getHeader.BytesUsed {
+	case "":
+		h.BytesUsed = 0
+	default:
+		h.BytesUsed, err = strconv.ParseInt(getHeader.BytesUsed, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	fmt.Println("getHeader: ", getHeader.ContentLength)
+	switch getHeader.ContentLength {
+	case "":
+		h.ContentLength = 0
+	default:
+		h.ContentLength, err = strconv.ParseInt(getHeader.ContentLength, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	switch getHeader.ObjectCount {
+	case "":
+		h.ObjectCount = 0
+	default:
+		h.ObjectCount, err = strconv.ParseInt(getHeader.ObjectCount, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	switch getHeader.ContainerCount {
+	case "":
+		h.ContainerCount = 0
+	default:
+		h.ContainerCount, err = strconv.ParseInt(getHeader.ContainerCount, 10, 64)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
 }
 
 // GetResult is returned from a call to the Get function.
diff --git a/openstack/objectstorage/v1/accounts/testing/fixtures.go b/openstack/objectstorage/v1/accounts/testing/fixtures.go
index a265199..fff3071 100644
--- a/openstack/objectstorage/v1/accounts/testing/fixtures.go
+++ b/openstack/objectstorage/v1/accounts/testing/fixtures.go
@@ -16,6 +16,7 @@
 		th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
 
 		w.Header().Set("X-Account-Container-Count", "2")
+		w.Header().Set("X-Account-Object-Count", "5")
 		w.Header().Set("X-Account-Bytes-Used", "14")
 		w.Header().Set("X-Account-Meta-Subject", "books")
 		w.Header().Set("Date", "Fri, 17 Jan 2014 16:09:56 GMT")
diff --git a/openstack/objectstorage/v1/accounts/testing/requests_test.go b/openstack/objectstorage/v1/accounts/testing/requests_test.go
index cf3fe05..dc5d9de 100644
--- a/openstack/objectstorage/v1/accounts/testing/requests_test.go
+++ b/openstack/objectstorage/v1/accounts/testing/requests_test.go
@@ -2,20 +2,33 @@
 
 import (
 	"testing"
+	"time"
 
+	"github.com/gophercloud/gophercloud"
 	"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts"
 	th "github.com/gophercloud/gophercloud/testhelper"
 	fake "github.com/gophercloud/gophercloud/testhelper/client"
 )
 
+var (
+	loc, _ = time.LoadLocation("GMT")
+)
+
 func TestUpdateAccount(t *testing.T) {
 	th.SetupHTTP()
 	defer th.TeardownHTTP()
 	HandleUpdateAccountSuccessfully(t)
 
 	options := &accounts.UpdateOpts{Metadata: map[string]string{"gophercloud-test": "accounts"}}
-	_, err := accounts.Update(fake.ServiceClient(), options).Extract()
+	res := accounts.Update(fake.ServiceClient(), options)
+	th.AssertNoErr(t, res.Err)
+
+	expected := &accounts.UpdateHeader{
+		Date: gophercloud.JSONRFC1123(time.Date(2014, time.January, 17, 16, 9, 56, 0, loc)), // Fri, 17 Jan 2014 16:09:56 GMT
+	}
+	actual, err := res.Extract()
 	th.AssertNoErr(t, err)
+	th.CheckDeepEquals(t, expected, actual)
 }
 
 func TestGetAccount(t *testing.T) {
@@ -30,4 +43,14 @@
 	th.CheckDeepEquals(t, expectedMetadata, actualMetadata)
 	_, err := res.Extract()
 	th.AssertNoErr(t, err)
+
+	expected := &accounts.GetHeader{
+		ContainerCount: 2,
+		ObjectCount:    5,
+		BytesUsed:      14,
+		Date:           gophercloud.JSONRFC1123(time.Date(2014, time.January, 17, 16, 9, 56, 0, loc)), // Fri, 17 Jan 2014 16:09:56 GMT
+	}
+	actual, err := res.Extract()
+	th.AssertNoErr(t, err)
+	th.CheckDeepEquals(t, expected, actual)
 }