structDeserializeImpl sname fields
 = do sayln' $ structDeserializeProto sname ++ " {"
      sayln' $ "  int ret = 0;"
      when (any isResizable fields) (sayln' $ "  " ++ intType IKUnsigned IS32 ++ " temp = 0;")
      sayln' $ "  "
      flip mapM_ fields $ \(StructField{ field_name = fname, field_array = farray, field_type = ftype })
        -> case farray of
            Scalar ->
              do sayln' $ "  ret = " ++ deserialize ftype ++ "(in, in_len, pos, &out->" ++ fname ++ ");"
                 sayln' $ "  if (ret) return ret;"
            Fixed _ ->
              do sayln' $ "  for (int i = 0; i < " ++ arrayLenFixed sname fname ++ "; i++) {"
                 sayln' $ "    ret = " ++ deserialize ftype ++ "(in, in_len, pos, &out->" ++ fname ++ "[i]);"
                 sayln' $ "    if (ret) return ret;"
                 sayln' $ "  }"
            Max _ ->
              do sayln' $ "  ret = " ++ deserialize (FInt IKUnsigned IS32) ++ "(in, in_len, pos, &temp);"
                 sayln' $ "  if (ret) return ret;"
                 sayln' $ "  ret = " ++ arrayResize sname fname ++ "(out, temp);"
                 sayln' $ "  if (ret) return ret;"
                 sayln' $ "  for (int i = 0; i < out->" ++ arrayLen fname ++ "; i++) {"
                 sayln' $ "    ret = " ++ deserialize ftype ++ "(in, in_len, pos, &out->" ++ fname ++ "[i]);"
                 sayln' $ "    if (ret) return ret;"
                 sayln' $ "  }"
      sayln' $ "  "
      sayln' $ "  return ret;"
      sayln' $ "}"
structDeserializeImpl sname fields
 = do sayln' $ structDeserializeProto sname ++ " {"
      sayln' $ "  int ret = 0;"
      when (any isResizable fields) (sayln' $ "  " ++ intType IKUnsigned IS32 ++ " temp = 0;")
      sayln' $ "  "
      flip mapM_ fields $ \(StructField{ field_name = fname, field_array = farray, field_type = ftype })
        -> case farray of
            Scalar ->
              do sayln' $ "  ret = " ++ deserialize ftype ++ "(in, in_len, pos, &out->" ++ fname ++ ");"
                 sayln' $ "  if (ret) return ret;"
            Fixed _ ->
              do sayln' $ "  for (int i = 0; i < " ++ arrayLenFixed sname fname ++ "; i++) {"
                 sayln' $ "    ret = " ++ deserialize ftype ++ "(in, in_len, pos, &out->" ++ fname ++ "[i]);"
                 sayln' $ "    if (ret) return ret;"
                 sayln' $ "  }"
            Max _ ->
              do sayln' $ "  ret = " ++ deserialize (FInt IKUnsigned IS32) ++ "(in, in_len, pos, &temp);"
                 sayln' $ "  if (ret) return ret;"
                 sayln' $ "  ret = " ++ arrayResize sname fname ++ "(out, temp);"
                 sayln' $ "  if (ret) return ret;"
                 sayln' $ "  for (int i = 0; i < out->" ++ arrayLen fname ++ "; i++) {"
                 sayln' $ "    ret = " ++ deserialize ftype ++ "(in, in_len, pos, &out->" ++ fname ++ "[i]);"
                 sayln' $ "    if (ret) return ret;"
                 sayln' $ "  }"
      sayln' $ "  "
      sayln' $ "  return ret;"
      sayln' $ "}"
structDeserializeImpl sname fields
 = do sayln' $ structDeserializeProto sname ++ " {"
      sayln' $ "  int ret = 0;"
      when (any isResizable fields) (sayln' $ "  " ++ intType IKUnsigned IS32 ++ " temp = 0;")
      sayln' $ "  "
      flip mapM_ fields $ \(StructField{ field_name = fname, field_array = farray, field_type = ftype })
        -> case farray of
            Scalar ->
              do sayln' $ "  ret = " ++ deserialize ftype ++ "(in, in_len, pos, &out->" ++ fname ++ ");"
                 sayln' $ "  if (ret) return ret;"
            Fixed _ ->
              do sayln' $ "  for (int i = 0; i < " ++ arrayLenFixed sname fname ++ "; i++) {"
                 sayln' $ "    ret = " ++ deserialize ftype ++ "(in, in_len, pos, &out->" ++ fname ++ "[i]);"
                 sayln' $ "    if (ret) return ret;"
                 sayln' $ "  }"
            Max _ ->
              do sayln' $ "  ret = " ++ deserialize (FInt IKUnsigned IS32) ++ "(in, in_len, pos, &temp);"
                 sayln' $ "  if (ret) return ret;"
                 sayln' $ "  ret = " ++ arrayResize sname fname ++ "(out, temp);"
                 sayln' $ "  if (ret) return ret;"
                 sayln' $ "  for (int i = 0; i < out->" ++ arrayLen fname ++ "; i++) {"
                 sayln' $ "    ret = " ++ deserialize ftype ++ "(in, in_len, pos, &out->" ++ fname ++ "[i]);"
                 sayln' $ "    if (ret) return ret;"
                 sayln' $ "  }"
      sayln' $ "  "
      sayln' $ "  return ret;"
      sayln' $ "}"