# Licensed to Elasticsearch B.V. under one or more contributor
# license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright
# ownership. Elasticsearch B.V. licenses this file to you under
# the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

import:
  - types.yml

main: |
  package gotype

  import (
    "reflect"

    stunsafe "github.com/urso/go-structform/internal/unsafe"
  )

  var _mapInlineMapping = map[reflect.Type]reFoldFn{
    {{ range data.primitiveTypes }}
      {{- $t := capitalize . -}}
    t{{ $t }}: foldMapInline{{ $t }},
    {{ end }}
  }

  func getMapInlineByPrimitiveElem(t reflect.Type) reFoldFn {
    if t == tInterface {
      return foldMapInlineInterface
    }
    return _mapInlineMapping[t]
  }

  func foldMapInlineInterface(C *foldContext, v reflect.Value) (err error) {
    ptr := unsafe.Pointer(v.Pointer())
    if ptr == nil {
      return nil
    }

    m := *((*map[string]interface{})(unsafe.Pointer(&ptr)))
    for k, v := range m {
      if err = C.OnKey(k); err != nil {
        return err
      }
      if err = foldInterfaceValue(C, v); err != nil {
        return err
      }
    }
    return
  }

  {{ range data.primitiveTypes }}
    {{ $t := capitalize . }}
    func foldMapInline{{ $t }}(C *foldContext, v reflect.Value) (err error) {
      ptr := unsafe.Pointer(v.Pointer())
      if ptr == nil {
        return nil
      }

      m := *((*map[string]{{ . }})(unsafe.Pointer(&ptr)))
      for k, v := range m {
        if err = C.OnKey(k); err != nil {
          return err
        }
        if err = C.On{{ $t }}(v); err != nil {
          return err
        }
      }
      return
    }
  {{ end }}
