Keystone Identity /v3/role_assignments
diff --git a/openstack/identity/v3/roles/results.go b/openstack/identity/v3/roles/results.go
new file mode 100644
index 0000000..31cb7a3
--- /dev/null
+++ b/openstack/identity/v3/roles/results.go
@@ -0,0 +1,64 @@
+package roles
+
+import (
+	"github.com/rackspace/gophercloud/pagination"
+
+	"github.com/mitchellh/mapstructure"
+)
+
+// RoleAssignment is the result of a role assignments query.
+type RoleAssignment struct {
+	Role  *Role  `json:"role,omitempty"`
+	Scope *Scope `json:"scope,omitempty"`
+	User  *User  `json:"user,omitempty"`
+	Group *Group `json:"group,omitempty"`
+}
+
+type Role struct {
+	ID string `json:"id,omitempty"`
+}
+
+type Scope struct {
+	Domain  *Domain  `json:"domain,omitempty"`
+	Project *Project `json:"domain,omitempty"`
+}
+
+type Domain struct {
+	ID string `json:"id,omitempty"`
+}
+
+type Project struct {
+	ID string `json:"id,omitempty"`
+}
+
+type User struct {
+	ID string `json:"id,omitempty"`
+}
+
+type Group struct {
+	ID string `json:"id,omitempty"`
+}
+
+// RoleAssignmentsPage is a single page of RoleAssignments results.
+type RoleAssignmentsPage struct {
+	pagination.LinkedPageBase
+}
+
+// IsEmpty returns true if the page contains no results.
+func (p RoleAssignmentsPage) IsEmpty() (bool, error) {
+	roleAssignments, err := ExtractRoleAssignments(p)
+	if err != nil {
+		return true, err
+	}
+	return len(roleAssignments) == 0, nil
+}
+
+// ExtractRoleAssignments extracts a slice of RoleAssignments from a Collection acquired from List.
+func ExtractRoleAssignments(page pagination.Page) ([]RoleAssignment, error) {
+	var response struct {
+		RoleAssignments []RoleAssignment `mapstructure:"role_assignments"`
+	}
+
+	err := mapstructure.Decode(page.(RoleAssignmentsPage).Body, &response)
+	return response.RoleAssignments, err
+}