ronantakizawa/codereview-bench huggingface dataset:
Repository: fmtlib/fmt
File: src/os.cc (C++)

Code before:

#  if FMT_USE_FCNTL
#    include <sys/stat.h>
#    include <sys/types.h>

#    ifdef _WRS_KERNEL    // VxWorks7 kernel
#      include <ioLib.h>  // getpagesize
#    endif

#    ifndef _WIN32
#      include <unistd.h>
#    else
#      ifndef WIN32_LEAN_AND_MEAN
#        define WIN32_LEAN_AND_MEAN
#      endif
#      include <io.h>
#    endif  // _WIN32
#  endif    // FMT_USE_FCNTL

#  ifdef _WIN32
#    include <windows.h>
#  endif
#endif

#if FMT_USE_FCNTL
#  ifdef _WIN32
#    ifndef S_IRUSR
#      define S_IRUSR _S_IREAD
#    endif
#    ifndef S_IWUSR
#      define S_IWUSR _S_IWRITE
#    endif
#    ifndef S_IRGRP
#      define S_IRGRP 0
#    endif
#    ifndef S_IWGRP
#      define S_IWGRP 0
#    endif
#    ifndef S_IROTH
#      define S_IROTH 0
#    endif
#    ifndef S_IWOTH
#      define S_IWOTH 0
#    endif
#  endif  // _WIN32
#endif    // FMT_USE_FCNTL

namespace {
#ifdef _WIN32
// Return type of read and write functions.
using rwresult = int;

Review comment (suggestion):
We can merge these two now to reduce nesting:

```
#if FMT_USE_FCNTL && defined(_WIN32)
```

Code after:

#  if FMT_USE_FCNTL
#    include <sys/stat.h>
#    include <sys/types.h>

#    ifdef _WRS_KERNEL    // VxWorks7 kernel
#      include <ioLib.h>  // getpagesize
#    endif

#    ifndef _WIN32
#      include <unistd.h>
#    else
#      ifndef WIN32_LEAN_AND_MEAN
#        define WIN32_LEAN_AND_MEAN
#      endif
#      include <io.h>
#    endif  // _WIN32
#  endif    // FMT_USE_FCNTL

#  ifdef _WIN32
#    include <windows.h>
#  endif
#endif

#ifdef _WIN32
#  ifndef S_IRUSR
#    define S_IRUSR _S_IREAD
#  endif
#  ifndef S_IWUSR
#    define S_IWUSR _S_IWRITE
#  endif
#  ifndef S_IRGRP
#    define S_IRGRP 0
#  endif
#  ifndef S_IWGRP
#    define S_IWGRP 0
#  endif
#  ifndef S_IROTH
#    define S_IROTH 0
#  endif
#  ifndef S_IWOTH
#    define S_IWOTH 0
#  endif
#endif

namespace {
#ifdef _WIN32
// Return type of read and write functions.
using rwresult = int;

// On Windows the count argument to read and write is unsigned, so convert
Repository: fmtlib/fmt
File: src/os.cc (C++)

Code before:

#  if FMT_USE_FCNTL
#    include <sys/stat.h>
#    include <sys/types.h>

#    ifdef _WRS_KERNEL    // VxWorks7 kernel
#      include <ioLib.h>  // getpagesize
#    endif

#    ifndef _WIN32
#      include <unistd.h>
#    else
#      ifndef WIN32_LEAN_AND_MEAN
#        define WIN32_LEAN_AND_MEAN
#      endif
#      include <io.h>
#    endif  // _WIN32
#  endif    // FMT_USE_FCNTL

#  ifdef _WIN32
#    include <windows.h>
#  endif
#endif

#if FMT_USE_FCNTL
#  ifdef _WIN32
#    ifndef S_IRUSR
#      define S_IRUSR _S_IREAD
#    endif
#    ifndef S_IWUSR
#      define S_IWUSR _S_IWRITE
#    endif
#    ifndef S_IRGRP
#      define S_IRGRP 0
#    endif
#    ifndef S_IWGRP
#      define S_IWGRP 0
#    endif
#    ifndef S_IROTH
#      define S_IROTH 0
#    endif
#    ifndef S_IWOTH
#      define S_IWOTH 0
#    endif
#  endif  // _WIN32
#endif    // FMT_USE_FCNTL

namespace {
#ifdef _WIN32
// Return type of read and write functions.
using rwresult = int;

Review comment (suggestion):
```suggestion
#if defined(FMT_USE_FCNTL) && defined(_WIN32)
```

Code after:

#  if FMT_USE_FCNTL
#    include <sys/stat.h>
#    include <sys/types.h>

#    ifdef _WRS_KERNEL    // VxWorks7 kernel
#      include <ioLib.h>  // getpagesize
#    endif

#    ifndef _WIN32
#      include <unistd.h>
#    else
#      ifndef WIN32_LEAN_AND_MEAN
#        define WIN32_LEAN_AND_MEAN
#      endif
#      include <io.h>
#    endif  // _WIN32
#  endif    // FMT_USE_FCNTL

#  ifdef _WIN32
#    include <windows.h>
#  endif
#endif

#ifdef _WIN32
#  ifndef S_IRUSR
#    define S_IRUSR _S_IREAD
#  endif
#  ifndef S_IWUSR
#    define S_IWUSR _S_IWRITE
#  endif
#  ifndef S_IRGRP
#    define S_IRGRP 0
#  endif
#  ifndef S_IWGRP
#    define S_IWGRP 0
#  endif
#  ifndef S_IROTH
#    define S_IROTH 0
#  endif
#  ifndef S_IWOTH
#    define S_IWOTH 0
#  endif
#endif

namespace {
#ifdef _WIN32
// Return type of read and write functions.
using rwresult = int;

// On Windows the count argument to read and write is unsigned, so convert
Repository: fmtlib/fmt
File: include/fmt/base.h (C/C++)

Code before:
    while (begin != end) {
      auto count = to_unsigned(end - begin);
      try_reserve(size_ + count);
      auto free_cap = capacity_ - size_;
      if (free_cap < count) count = free_cap;
      // A loop is faster than memcpy on small sizes.
      T* out = ptr_ + size_;
      for (size_t i = 0; i < count; ++i) out[i] = begin[i];
      size_ += count;
      begin += count;
    }
  }

  template <typename Idx> FMT_CONSTEXPR auto operator[](Idx index) -> T& {
    return ptr_[index];
  }
  template <typename Idx>
  FMT_CONSTEXPR auto operator[](Idx index) const -> const T& {
    return ptr_[index];
  }
};

struct buffer_traits {
  FMT_CONSTEXPR explicit buffer_traits(size_t) {}
  FMT_CONSTEXPR auto count() const -> size_t { return 0; }
  FMT_CONSTEXPR auto limit(size_t size) -> size_t { return size; }
};

class fixed_buffer_traits {
 private:
  size_t count_ = 0;
  size_t limit_;

 public:
  FMT_CONSTEXPR explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
  FMT_CONSTEXPR auto count() const -> size_t { return count_; }
  FMT_CONSTEXPR auto limit(size_t size) -> size_t {
    size_t n = limit_ > count_ ? limit_ - count_ : 0;
    count_ += size;
    return size < n ? size : n;
  }
};

// A buffer that writes to an output iterator when flushed.
template <typename OutputIt, typename T, typename Traits = buffer_traits>
class iterator_buffer : public Traits, public buffer<T> {
 private:
  OutputIt out_;
  enum { buffer_size = 256 };
  T data_[buffer_size];


Review comment (suggestion):
These can be `constexpr`. `FMT_CONSTEXPR` is only for cases when C++14 relaxed `constexpr` is needed.

Code after:
      if (free_cap < count) count = free_cap;
      // A loop is faster than memcpy on small sizes.
      T* out = ptr_ + size_;
      for (size_t i = 0; i < count; ++i) out[i] = begin[i];
      size_ += count;
      begin += count;
    }
  }

  template <typename Idx> FMT_CONSTEXPR auto operator[](Idx index) -> T& {
    return ptr_[index];
  }
  template <typename Idx>
  FMT_CONSTEXPR auto operator[](Idx index) const -> const T& {
    return ptr_[index];
  }
};

struct buffer_traits {
  constexpr explicit buffer_traits(size_t) {}
  constexpr auto count() const -> size_t { return 0; }
  constexpr auto limit(size_t size) const -> size_t { return size; }
};

class fixed_buffer_traits {
 private:
  size_t count_ = 0;
  size_t limit_;

 public:
  constexpr explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
  constexpr auto count() const -> size_t { return count_; }
  FMT_CONSTEXPR auto limit(size_t size) -> size_t {
    size_t n = limit_ > count_ ? limit_ - count_ : 0;
    count_ += size;
    return size < n ? size : n;
  }
};

// A buffer that writes to an output iterator when flushed.
template <typename OutputIt, typename T, typename Traits = buffer_traits>
class iterator_buffer : public Traits, public buffer<T> {
 private:
  OutputIt out_;
  enum { buffer_size = 256 };
  T data_[buffer_size];

  static FMT_CONSTEXPR void grow(buffer<T>& buf, size_t) {
    if (buf.size() == buffer_size) static_cast<iterator_buffer&>(buf).flush();
  }
Repository: fmtlib/fmt
File: support/python/mkdocstrings_handlers/cxx/__init__.py (Python)

Code before:
# A basic mkdocstrings handler for {fmt}.
# Copyright (c) 2012 - present, Victor Zverovich
# https://github.com/fmtlib/fmt/blob/master/LICENSE

# pyright: strict

import os
import xml.etree.ElementTree as ET
from pathlib import Path
from subprocess import PIPE, STDOUT, CalledProcessError, Popen
from typing import Any, ClassVar, TYPE_CHECKING, final, override

from markupsafe import Markup
from mkdocstrings import BaseHandler

if TYPE_CHECKING:
    from collections.abc import Mapping, MutableMapping
    from mkdocs.config.defaults import MkDocsConfig
    from mkdocstrings import CollectorItem, HandlerOptions


@final
class Definition:
    """A definition extracted by Doxygen."""

    def __init__(
        self,
        name: str,
        kind: "str | None" = None,
        node: "ET.Element | None" = None,
        is_member: bool = False,
    ):
        self.name = name
        self.kind: "str | None" = None
        if kind is not None:
            self.kind = kind

Review comment (suggestion):
CI complains about `override`: 

```
ImportError: cannot import name 'override' from 'typing' (/usr/lib/python3.10/typing.py)
```
https://github.com/fmtlib/fmt/actions/runs/20028626137/job/57455771194

Code after:
# A basic mkdocstrings handler for {fmt}.
# Copyright (c) 2012 - present, Victor Zverovich
# https://github.com/fmtlib/fmt/blob/master/LICENSE

# pyright: strict

import os
import xml.etree.ElementTree as ET
from pathlib import Path
from subprocess import PIPE, STDOUT, CalledProcessError, Popen

from markupsafe import Markup
from mkdocstrings import BaseHandler
from typing_extensions import TYPE_CHECKING, Any, ClassVar, final, override

if TYPE_CHECKING:
    from collections.abc import Mapping, MutableMapping

    from mkdocs.config.defaults import MkDocsConfig
    from mkdocstrings import CollectorItem, HandlerOptions


@final
class Definition:
    """A definition extracted by Doxygen."""

    def __init__(
        self,
        name: str,
        kind: "str | None" = None,
        node: "ET.Element | None" = None,
        is_member: bool = False,
    ):
        self.name = name
        self.kind: "str | None" = None
        if kind is not None:
Repository: fmtlib/fmt
File: test/ranges-test.cc (C++)

Code before:
// Formatting library for C++ - ranges tests
//
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
// All rights reserved.
//
// For the license information refer to format.h.

#include "fmt/ranges.h"

#include <array>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <stack>
#include <string>
#include <utility>
#include <vector>

#include "fmt/base.h"
#include "fmt/ranges.h"
#include "posix-mock.h"

#if FMT_CPLUSPLUS > 201703L && FMT_HAS_INCLUDE(<ranges>)
#  include <ranges>
#endif

#include "fmt/format.h"
#include "gtest/gtest.h"

#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 601
#  define FMT_RANGES_TEST_ENABLE_C_STYLE_ARRAY
#endif

#ifdef FMT_RANGES_TEST_ENABLE_C_STYLE_ARRAY
TEST(ranges_test, format_array) {
  int arr[] = {1, 2, 3, 5, 7, 11};
  EXPECT_EQ(fmt::format("{}", arr), "[1, 2, 3, 5, 7, 11]");
}

TEST(ranges_test, format_2d_array) {
  int arr[][2] = {{1, 2}, {3, 5}, {7, 11}};
  EXPECT_EQ(fmt::format("{}", arr), "[[1, 2], [3, 5], [7, 11]]");
}

TEST(ranges_test, format_array_of_literals) {
  const char* arr[] = {"1234", "abcd"};

Review comment (suggestion):
I don't think we need these. `fmt/ranges.h` is included above and is effectively a superset of `fmt/base.h`.

Code after:
// Formatting library for C++ - ranges tests
//
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
// All rights reserved.
//
// For the license information refer to format.h.

#include "fmt/ranges.h"

#include <array>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <stack>
#include <string>
#include <utility>
#include <vector>

#if FMT_CPLUSPLUS > 201703L && FMT_HAS_INCLUDE(<ranges>)
#  include <ranges>
#endif

#include "fmt/format.h"
#include "gtest/gtest.h"

#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 601
#  define FMT_RANGES_TEST_ENABLE_C_STYLE_ARRAY
#endif

#ifdef FMT_RANGES_TEST_ENABLE_C_STYLE_ARRAY
TEST(ranges_test, format_array) {
  int arr[] = {1, 2, 3, 5, 7, 11};
  EXPECT_EQ(fmt::format("{}", arr), "[1, 2, 3, 5, 7, 11]");
}

TEST(ranges_test, format_2d_array) {
  int arr[][2] = {{1, 2}, {3, 5}, {7, 11}};
  EXPECT_EQ(fmt::format("{}", arr), "[[1, 2], [3, 5], [7, 11]]");
}

TEST(ranges_test, format_array_of_literals) {
  const char* arr[] = {"1234", "abcd"};
  EXPECT_EQ(fmt::format("{}", arr), "[\"1234\", \"abcd\"]");
  EXPECT_EQ(fmt::format("{:n}", arr), "\"1234\", \"abcd\"");
  EXPECT_EQ(fmt::format("{:n:}", arr), "1234, abcd");
}
Repository: freeCodeCamp/freeCodeCamp
File: api/src/routes/challenge.ts (TypeScript)

Code before:
    }
  );

  fastify.post(
    '/save-challenge',
    {
      schema: schemas.saveChallenge,
      errorHandler(error, request, reply) {
        if (error.validation) {
          void reply.code(403);
          return formatValidationError(
            error.validation,
            'That challenge type is not savable.'
          );
        } else {
          fastify.errorHandler(error, request, reply);
        }
      }
    },
    async (req, reply) => {
      try {
        const { files, id: challengeId } = req.body;
        const user = await fastify.prisma.user.findUniqueOrThrow({
          where: { id: req.session.user.id }
        });
        const savableChallenges = user.savedChallenges;
        const challenge = {
          id: challengeId,
          files
        };

        console.log(savableChallenges.filter(c => c.id === challengeId));
        if (!savableChallenges.filter(c => c.id === challengeId)) {
          void reply.code(403);
          return {
            type: 'error',
            message: 'That challenge type is not savable.'
          } as const;
        }

        const userSavedChallenges = saveUserChallengeData(
          challengeId,
          user,
          challenge
        );

        await fastify.prisma.user.update({
          where: { id: user.id },
          data: {
            savedChallenges: userSavedChallenges
          }

Review comment (suggestion):
This is the currently saved challenges, not the challenges that can be saved. Those are challenges with type `multifileCertProject`

Code after:
          fastify.errorHandler(error, request, reply);
        }
      }
    },
    async (req, reply) => {
      try {
        const { files, id: challengeId } = req.body;
        const user = await fastify.prisma.user.findUniqueOrThrow({
          where: { id: req.session.user.id }
        });
        const challenge = {
          id: challengeId,
          files
        };

        if (!multifileCertProjectIds.includes(challengeId)) {
          void reply.code(403);
          return 'That challenge type is not savable.';
        }

        const userSavedChallenges = saveUserChallengeData(
          challengeId,
          user.savedChallenges,
          challenge
        );

        await fastify.prisma.user.update({
          where: { id: user.id },
          data: {
            savedChallenges: userSavedChallenges
          }
        });

        return { savedChallenges: userSavedChallenges };
      } catch (error) {
        fastify.log.error(error);
        void reply.code(500);
        return {
          message:
            'Oops! Something went wrong. Please try again in a moment or contact support@freecodecamp.org if the error persists.',
          type: 'danger'
        } as const;
      }
    }
  );

  done();
};
Repository: freeCodeCamp/freeCodeCamp
File: api/src/routes/challenge.ts (TypeScript)

Code before:
          fastify.errorHandler(error, request, reply);
        }
      }
    },
    async (req, reply) => {
      try {
        const { files, id: challengeId } = req.body;
        const user = await fastify.prisma.user.findUniqueOrThrow({
          where: { id: req.session.user.id }
        });
        const challenge = {
          id: challengeId,
          files
        };

        if (!multifileCertProjectIds.includes(challengeId)) {
          void reply.code(403);
          return {
            type: 'error',
            message: 'That challenge type is not savable.'
          } as const;
        }

        const userSavedChallenges = saveUserChallengeData(
          challengeId,
          user,
          challenge
        );

        await fastify.prisma.user.update({
          where: { id: user.id },
          data: {
            savedChallenges: userSavedChallenges
          }
        });

        return { savedChallenges: userSavedChallenges };
      } catch (error) {
        fastify.log.error(error);
        void reply.code(500);
        return {
          message:
            'Oops! Something went wrong. Please try again in a moment or contact support@freecodecamp.org if the error persists.',
          type: 'danger'
        } as const;
      }
    }
  );

  done();
};

Review comment (suggestion):
```suggestion
          user.savedChallenges,
```
The function only needs `savedChallenges`, so we can do that rather than passing in the user object.

Code after:
    },
    async (req, reply) => {
      try {
        const { files, id: challengeId } = req.body;
        const user = await fastify.prisma.user.findUniqueOrThrow({
          where: { id: req.session.user.id }
        });
        const challenge = {
          id: challengeId,
          files
        };

        if (!multifileCertProjectIds.includes(challengeId)) {
          void reply.code(403);
          return 'That challenge type is not savable.';
        }

        const userSavedChallenges = saveUserChallengeData(
          challengeId,
          user.savedChallenges,
          challenge
        );

        await fastify.prisma.user.update({
          where: { id: user.id },
          data: {
            savedChallenges: userSavedChallenges
          }
        });

        return { savedChallenges: userSavedChallenges };
      } catch (error) {
        fastify.log.error(error);
        void reply.code(500);
        return {
          message:
            'Oops! Something went wrong. Please try again in a moment or contact support@freecodecamp.org if the error persists.',
          type: 'danger'
        } as const;
      }
    }
  );

  done();
};
Repository: freeCodeCamp/freeCodeCamp
File: api/src/schemas.ts (TypeScript)

Code before:
import { Type } from '@fastify/type-provider-typebox';

const generic500 = Type.Object({
  message: Type.Literal(
    'Oops! Something went wrong. Please try again in a moment or contact support@freecodecamp.org if the error persists.'
  ),
  type: Type.Literal('danger')
});

const file = Type.Object({
  contents: Type.String(),
  key: Type.String(),
  ext: Type.String(),
  name: Type.String(),
  history: Type.Array(Type.String())
});

const saveChallengeBody = Type.Object({
  id: Type.String({
    format: 'objectid',
    maxLength: 24,
    minLength: 24
  }),
  lastSavedDate: Type.Number(),
  files: Type.Array(file)
});

export const schemas = {
  // Settings:
  updateMyProfileUI: {
    body: Type.Object({
      profileUI: Type.Object({
        isLocked: Type.Boolean(),
        showAbout: Type.Boolean(),
        showCerts: Type.Boolean(),
        showDonation: Type.Boolean(),
        showHeatMap: Type.Boolean(),
        showLocation: Type.Boolean(),
        showName: Type.Boolean(),
        showPoints: Type.Boolean(),
        showPortfolio: Type.Boolean(),
        showTimeLine: Type.Boolean()
      })
    }),
    response: {
      200: Type.Object({
        message: Type.Literal('flash.privacy-updated'),
        type: Type.Literal('success')
      }),

Review comment (suggestion):
```suggestion
```
The body doesn't have this property.

Code after:
import { Type } from '@fastify/type-provider-typebox';

const generic500 = Type.Object({
  message: Type.Literal(
    'Oops! Something went wrong. Please try again in a moment or contact support@freecodecamp.org if the error persists.'
  ),
  type: Type.Literal('danger')
});

const file = Type.Object({
  contents: Type.String(),
  key: Type.String(),
  ext: Type.String(),
  name: Type.String(),
  history: Type.Array(Type.String())
});

const saveChallengeBody = Type.Object({
  id: Type.String({
    format: 'objectid',
    maxLength: 24,
    minLength: 24
  }),
  files: Type.Array(file)
});

export const schemas = {
  // Settings:
  updateMyProfileUI: {
    body: Type.Object({
      profileUI: Type.Object({
        isLocked: Type.Boolean(),
        showAbout: Type.Boolean(),
        showCerts: Type.Boolean(),
        showDonation: Type.Boolean(),
        showHeatMap: Type.Boolean(),
        showLocation: Type.Boolean(),
        showName: Type.Boolean(),
        showPoints: Type.Boolean(),
        showPortfolio: Type.Boolean(),
        showTimeLine: Type.Boolean()
      })
    }),
    response: {
      200: Type.Object({
        message: Type.Literal('flash.privacy-updated'),
        type: Type.Literal('success')
      }),
      500: Type.Object({
Repository: freeCodeCamp/freeCodeCamp
File: api/src/utils/common-challenge-functions.ts (TypeScript)

Code before:
  // This value is present in prisma schema
  path?: string | null;
};

export type CompletedChallenge = {
  id: string;
  solution?: string | null;
  githubLink?: string | null;
  challengeType?: number | null;
  completedDate: number;
  isManuallyApproved?: boolean | null;
  files?: CompletedChallengeFile[];
};

/**
 * Helper function to save a user's challenge data. Used in challenge
 * submission endpoints.
 *
 * @param challengeId The id of the submitted challenge.
 * @param user The existing user record.
 * @param challenge The saveble challenge.
 * @returns Saved challenges.
 */
export function saveUserChallengeData(
  challengeId: string,
  user: user,
  challenge: Omit<SavedChallenge, 'lastSavedDate'>
) {
  const challengeToSave: SavedChallenge = {
    id: challengeId,
    lastSavedDate: Date.now(),
    files: challenge.files?.map(file =>
      pick(file, ['contents', 'key', 'name', 'ext', 'history'])
    ) as SavedChallengeFile[]
  };

  const savedIndex = user.savedChallenges.findIndex(
    ({ id }) => challengeId === id
  );

  if (savedIndex >= 0) {
    user.savedChallenges[savedIndex] = challengeToSave;
  } else {
    user.savedChallenges.push(challengeToSave);
  }

  return user.savedChallenges;
}

/**
 * Helper function to update a user's challenge data. Used in challenge

Review comment (suggestion):
```suggestion
  savedChallenges: SavedChallenge[],
```

Code after:
  // This value is present in prisma schema
  path?: string | null;
};

export type CompletedChallenge = {
  id: string;
  solution?: string | null;
  githubLink?: string | null;
  challengeType?: number | null;
  completedDate: number;
  isManuallyApproved?: boolean | null;
  files?: CompletedChallengeFile[];
};

/**
 * Helper function to save a user's challenge data. Used in challenge
 * submission endpoints.
 *
 * @param challengeId The id of the submitted challenge.
 * @param savedChallenges The user's saved challenges array.
 * @param challenge The saveble challenge.
 * @returns Update or push the saved challenges.
 */
export function saveUserChallengeData(
  challengeId: string,
  savedChallenges: SavedChallenge[],
  challenge: Omit<SavedChallenge, 'lastSavedDate'>
) {
  const challengeToSave: SavedChallenge = {
    id: challengeId,
    lastSavedDate: Date.now(),
    files: challenge.files?.map(file =>
      pick(file, ['contents', 'key', 'name', 'ext', 'history'])
    )
  };

  const savedIndex = savedChallenges.findIndex(({ id }) => challengeId === id);

  if (savedIndex >= 0) {
    savedChallenges[savedIndex] = challengeToSave;
  } else {
    savedChallenges.push(challengeToSave);
  }

  return savedChallenges;
}

/**
 * Helper function to update a user's challenge data. Used in challenge
 * submission endpoints.
 *