github.com/fraugster/parquet-go@v0.12.0/floor/interfaces/marshaller.go (about) 1 package interfaces 2 3 import "github.com/fraugster/parquet-go/parquetschema" 4 5 // Marshaller is the interface necessary for objects to be 6 // marshalled when passed to the (*Writer).WriteRecord method. 7 type Marshaller interface { 8 MarshalParquet(obj MarshalObject) error 9 } 10 11 // MarshalObject is the interface a Marshaller needs to marshall its data 12 // to. 13 type MarshalObject interface { 14 AddField(field string) MarshalElement 15 16 GetData() map[string]interface{} 17 } 18 19 // MarshalElement describes the interface to set the value of an element in a Marshaller 20 // implementation. 21 type MarshalElement interface { 22 Group() MarshalObject 23 SetInt32(i int32) 24 SetInt64(i int64) 25 SetInt96(i [12]byte) 26 SetFloat32(f float32) 27 SetFloat64(f float64) 28 SetBool(b bool) 29 SetByteArray(data []byte) 30 List() MarshalList 31 Map() MarshalMap 32 } 33 34 // MarshalList describes the interface to add a list of values in a Marshaller 35 // implementation. 36 type MarshalList interface { 37 Add() MarshalElement 38 } 39 40 // MarshalMap describes the interface to add a map of keys and values in a Marshaller 41 // implementation. 42 type MarshalMap interface { 43 Add() MarshalMapElement 44 } 45 46 // MarshalMapElement describes the interfaces to set an individual pair of keys and 47 // values in a Marshaller implementation. 48 type MarshalMapElement interface { 49 Key() MarshalElement 50 Value() MarshalElement 51 } 52 53 type object struct { 54 data map[string]interface{} 55 schema *parquetschema.SchemaDefinition 56 } 57 58 func (o *object) GetData() map[string]interface{} { 59 return o.data 60 } 61 62 func (o *object) AddField(field string) MarshalElement { 63 return &element{data: o.data, f: field, schema: o.schema.SubSchema(field)} 64 } 65 66 type element struct { 67 data map[string]interface{} 68 f string 69 schema *parquetschema.SchemaDefinition 70 } 71 72 func (e *element) SetInt32(i int32) { 73 e.data[e.f] = i 74 } 75 76 func (e *element) SetInt64(i int64) { 77 e.data[e.f] = i 78 } 79 80 func (e *element) SetInt96(i [12]byte) { 81 e.data[e.f] = i 82 } 83 84 func (e *element) SetFloat32(f float32) { 85 e.data[e.f] = f 86 } 87 88 func (e *element) SetFloat64(f float64) { 89 e.data[e.f] = f 90 } 91 92 func (e *element) SetBool(b bool) { 93 e.data[e.f] = b 94 } 95 96 func (e *element) SetByteArray(data []byte) { 97 e.data[e.f] = data 98 } 99 100 func (e *element) List() MarshalList { 101 listName := "list" 102 elemName := "element" 103 bagSchema := e.schema.SubSchema("bag") 104 if bagSchema != nil { 105 listName = "bag" 106 elemName = "array_element" 107 } 108 return &list{parentData: e.data, parentField: e.f, listName: listName, elemName: elemName, schema: e.schema.SubSchema(listName).SubSchema(elemName)} 109 } 110 111 func (e *element) Map() MarshalMap { 112 data := map[string]interface{}{"key_value": []map[string]interface{}{}} 113 e.data[e.f] = data 114 return &marshMap{data: data, schema: e.schema} 115 } 116 117 func (e *element) Group() MarshalObject { 118 obj := map[string]interface{}{} 119 e.data[e.f] = obj 120 return &object{data: obj} 121 } 122 123 type list struct { 124 parentData map[string]interface{} 125 parentField string 126 data map[string]interface{} 127 schema *parquetschema.SchemaDefinition 128 listName string 129 elemName string 130 } 131 132 func (l *list) Add() MarshalElement { 133 if l.data == nil { 134 l.data = map[string]interface{}{l.listName: []map[string]interface{}{}} 135 // we need to delay adding map to parent data field until Add() is called first time, otherwise 136 // this code will fail on an empty m.Foobar: 137 // 138 // list := obj.AddField("foobar").List() 139 // for _, elem := range m.Foobar { 140 // list.Add().SetByteArray([]byte(elem)) 141 // } 142 l.parentData[l.parentField] = l.data 143 } 144 listData := l.data[l.listName].([]map[string]interface{}) 145 elemData := map[string]interface{}{} 146 l.data[l.listName] = append(listData, elemData) 147 e := &element{data: elemData, f: l.elemName, schema: l.schema} 148 return e 149 } 150 151 type marshMap struct { 152 data map[string]interface{} 153 schema *parquetschema.SchemaDefinition 154 } 155 156 func (l *marshMap) Add() MarshalMapElement { 157 kvData := l.data["key_value"].([]map[string]interface{}) 158 elemData := map[string]interface{}{} 159 l.data["key_value"] = append(kvData, elemData) 160 me := &mapElement{data: elemData, schema: l.schema.SubSchema("key_value")} 161 return me 162 } 163 164 type mapElement struct { 165 data map[string]interface{} 166 schema *parquetschema.SchemaDefinition 167 } 168 169 func (m *mapElement) Key() MarshalElement { 170 return &element{data: m.data, f: "key", schema: m.schema.SubSchema("key")} 171 } 172 173 func (m *mapElement) Value() MarshalElement { 174 return &element{data: m.data, f: "value", schema: m.schema.SubSchema("value")} 175 } 176 177 // NewMarshallObject creates a new marshaller object 178 func NewMarshallObject(data map[string]interface{}) MarshalObject { 179 if data == nil { 180 data = make(map[string]interface{}) 181 } 182 return &object{ 183 data: data, 184 } 185 } 186 187 // NewMarshallObjectWithSchema creates a new marshaller object with a particular schema. 188 func NewMarshallObjectWithSchema(data map[string]interface{}, schemaDef *parquetschema.SchemaDefinition) MarshalObject { 189 if data == nil { 190 data = make(map[string]interface{}) 191 } 192 return &object{ 193 data: data, 194 schema: schemaDef, 195 } 196 } 197 198 // NewMarshalElement creates new marshall element object 199 func NewMarshalElement(data map[string]interface{}, name string) MarshalElement { 200 if data == nil { 201 data = make(map[string]interface{}) 202 } 203 return &element{ 204 data: data, 205 f: name, 206 } 207 }