2014-04-26 09:18:56 +00:00
package ICCC
2014-10-19 17:19:11 +00:00
import (
"fmt"
2015-06-21 18:18:23 +00:00
"github.com/SommerEngineering/Ocean/Log"
LM "github.com/SommerEngineering/Ocean/Log/Meta"
2014-10-19 17:19:11 +00:00
"reflect"
"strconv"
)
2014-04-26 09:18:56 +00:00
2015-06-17 15:44:52 +00:00
// Function to convert the HTTP data back to a message.
2014-04-26 09:18:56 +00:00
func Data2Message ( target interface { } , data map [ string ] [ ] string ) ( channel , command string , obj interface { } ) {
2015-06-21 18:18:23 +00:00
defer func ( ) {
if err := recover ( ) ; err != nil {
channel = ` `
command = ` `
obj = nil
Log . LogFull ( senderName , LM . CategorySYSTEM , LM . LevelERROR , LM . SeverityUnknown , LM . ImpactUnknown , LM . MessageNamePARSE , fmt . Sprintf ( "Was not able to convert the HTTP values to a message. %s" , err ) )
return
}
} ( )
2014-04-26 09:18:56 +00:00
if data == nil || len ( data ) == 0 {
channel = ` `
command = ` `
obj = nil
return
}
2015-06-21 18:18:23 +00:00
// By using reflection, determine the type:
elementType := reflect . TypeOf ( target )
// Is it a pointer?
if elementType . Kind ( ) == reflect . Ptr {
// Get the value behind the pointer:
elementType = elementType . Elem ( )
}
// ICCC works with structs! If this is not a struct, its an error.
if elementType . Kind ( ) != reflect . Struct {
Log . LogFull ( senderName , LM . CategorySYSTEM , LM . LevelERROR , LM . SeverityMiddle , LM . ImpactMiddle , LM . MessageNamePARSE , ` Was not able to transform HTTP data to a message, because the given data was not a struct. ` )
return
}
2014-04-26 09:18:56 +00:00
2015-06-21 18:18:23 +00:00
// By using reflection, create a new instance:
element := reflect . New ( elementType ) . Elem ( )
2014-04-26 09:18:56 +00:00
channel = data [ ` channel ` ] [ 0 ]
command = data [ ` command ` ] [ 0 ]
2015-06-17 15:44:52 +00:00
// Use the order of the destination type's fields:
2014-04-26 09:18:56 +00:00
for i := 0 ; i < element . NumField ( ) ; i ++ {
field := element . Field ( i )
switch field . Kind ( ) . String ( ) {
case ` int64 ` :
mapName := fmt . Sprintf ( ` int:%s ` , elementType . Field ( i ) . Name )
mapValue := data [ mapName ] [ 0 ]
v , _ := strconv . ParseInt ( mapValue , 10 , 64 )
field . SetInt ( v )
case ` string ` :
mapName := fmt . Sprintf ( ` str:%s ` , elementType . Field ( i ) . Name )
mapValue := data [ mapName ] [ 0 ]
field . SetString ( mapValue )
case ` float64 ` :
mapName := fmt . Sprintf ( ` f64:%s ` , elementType . Field ( i ) . Name )
mapValue := data [ mapName ] [ 0 ]
v , _ := strconv . ParseFloat ( mapValue , 64 )
field . SetFloat ( v )
case ` bool ` :
mapName := fmt . Sprintf ( ` bool:%s ` , elementType . Field ( i ) . Name )
mapValue := data [ mapName ] [ 0 ]
v , _ := strconv . ParseBool ( mapValue )
field . SetBool ( v )
case ` uint8 ` :
mapName := fmt . Sprintf ( ` ui8:%s ` , elementType . Field ( i ) . Name )
mapValue := data [ mapName ] [ 0 ]
v , _ := strconv . ParseUint ( mapValue , 16 , 8 )
field . SetUint ( v )
2015-06-17 15:44:52 +00:00
// Case: Arrays...
2014-04-26 09:18:56 +00:00
case ` slice ` :
sliceInterface := field . Interface ( )
sliceKind := reflect . ValueOf ( sliceInterface ) . Type ( ) . String ( )
switch sliceKind {
case ` []uint8 ` : // bytes
mapName := fmt . Sprintf ( ` ui8[]:%s ` , elementType . Field ( i ) . Name )
mapValues := data [ mapName ]
fieldLen := len ( mapValues )
fieldData := make ( [ ] uint8 , fieldLen , fieldLen )
for n , mapValue := range mapValues {
v , _ := strconv . ParseUint ( mapValue , 16 , 8 )
fieldData [ n ] = byte ( v )
}
fieldDataValue := reflect . ValueOf ( fieldData )
field . Set ( fieldDataValue )
case ` []int64 ` :
mapName := fmt . Sprintf ( ` int[]:%s ` , elementType . Field ( i ) . Name )
mapValues := data [ mapName ]
fieldLen := len ( mapValues )
fieldData := make ( [ ] int64 , fieldLen , fieldLen )
for n , mapValue := range mapValues {
v , _ := strconv . ParseInt ( mapValue , 10 , 64 )
fieldData [ n ] = v
}
fieldDataValue := reflect . ValueOf ( fieldData )
field . Set ( fieldDataValue )
case ` []bool ` :
mapName := fmt . Sprintf ( ` bool[]:%s ` , elementType . Field ( i ) . Name )
mapValues := data [ mapName ]
fieldLen := len ( mapValues )
fieldData := make ( [ ] bool , fieldLen , fieldLen )
for n , mapValue := range mapValues {
v , _ := strconv . ParseBool ( mapValue )
fieldData [ n ] = v
}
fieldDataValue := reflect . ValueOf ( fieldData )
field . Set ( fieldDataValue )
case ` []string ` :
mapName := fmt . Sprintf ( ` str[]:%s ` , elementType . Field ( i ) . Name )
mapValues := data [ mapName ]
fieldDataValue := reflect . ValueOf ( mapValues )
field . Set ( fieldDataValue )
case ` []float64 ` :
mapName := fmt . Sprintf ( ` f64[]:%s ` , elementType . Field ( i ) . Name )
mapValues := data [ mapName ]
fieldLen := len ( mapValues )
fieldData := make ( [ ] float64 , fieldLen , fieldLen )
for n , mapValue := range mapValues {
v , _ := strconv . ParseFloat ( mapValue , 64 )
fieldData [ n ] = v
}
fieldDataValue := reflect . ValueOf ( fieldData )
field . Set ( fieldDataValue )
}
}
}
2015-06-21 18:18:23 +00:00
obj = element . Interface ( )
2014-04-26 09:18:56 +00:00
return
}