import { expect, test } from 'vitest'
import type { OutputAsset, OutputChunk, RolldownOutput } from 'rolldown'
import { build } from 'vite'
import { browserLogs, getColor, isBuild, page, testDir } from '~utils'

test('should have no 404s', () => {
  browserLogs.forEach((msg) => {
    expect(msg).not.toMatch('404')
  })
})

test('index js', async () => {
  await expect.poll(() => page.textContent('.js')).toBe('js: ok')
})

test('importmap', async () => {
  await expect
    .poll(() => page.textContent('.importmap'))
    .toContain('"/foo": "/bar"')
})

test('static js', async () => {
  await expect.poll(() => page.textContent('.static-js')).toBe('static-js: ok')
})

test('dynamic js', async () => {
  await expect
    .poll(() => page.textContent('.dynamic-js'))
    .toBe('dynamic-js: ok')
})

test('static css', async () => {
  await expect.poll(() => getColor('.static')).toBe('red')
})

test('dynamic css', async () => {
  await expect.poll(() => getColor('.dynamic')).toBe('red')
})

test('direct dynamic css', async () => {
  await expect.poll(() => getColor('.direct-dynamic')).toBe('red')
})

// a CSS-only module shared by multiple chunks becomes a pure CSS chunk that is
// removed from the output. The import map must not keep referencing its removed
// JS file, otherwise chunks importing it 404 and fail to execute
// (https://github.com/vitejs/vite/issues/22740)
test('shared pure css chunk', async () => {
  await expect.poll(() => page.textContent('.shared-js')).toBe('shared-js: ok')
  await expect.poll(() => getColor('.shared')).toBe('green')
})

test('worker', async () => {
  await expect.poll(() => page.textContent('.worker')).toBe('worker: pong')
})

for (const cssFileName of ['dynamic.css', 'direct-dynamic.css']) {
  // This is a correctness requirement, not only a cache optimization: hashed
  // chunk filenames are cached as immutable. If the filename stayed the same
  // while its code changed to reference a new CSS filename, cached JS could
  // load stale CSS alongside newly mapped JS, breaking CSS module selectors.
  test.runIf(isBuild)(
    `${cssFileName} uses a stable import map specifier`,
    async () => {
      const buildWithColor = async (color: string) =>
        (await build({
          root: testDir,
          logLevel: 'silent',
          build: { write: false },
          plugins: [
            {
              name: 'change-dynamic-css',
              enforce: 'pre',
              transform(code, id) {
                if (id.endsWith(`/${cssFileName}`)) {
                  return code.replace('red', color)
                }
              },
            },
          ],
        })) as RolldownOutput

      const getIndexChunk = (output: RolldownOutput) =>
        output.output.find(
          (file): file is OutputChunk => file.type === 'chunk' && file.isEntry,
        )!
      const getImportMap = (output: RolldownOutput) =>
        JSON.parse(
          output.output
            .find(
              (file): file is OutputAsset => file.fileName === 'importmap.json',
            )!
            .source.toString(),
        ).imports as Record<string, string>
      const getCssFileName = (output: RolldownOutput) =>
        output.output.find(
          (file): file is OutputAsset =>
            file.type === 'asset' && file.names.includes(cssFileName),
        )!.fileName

      const redBuild = await buildWithColor('red')
      const blueBuild = await buildWithColor('blue')
      const redIndex = getIndexChunk(redBuild)
      const blueIndex = getIndexChunk(blueBuild)

      // The importer chunk does not change
      // because the CSS reference uses the hash in the import map
      expect(redIndex.fileName).toBe(blueIndex.fileName)
      expect(redIndex.code).toBe(blueIndex.code)

      const redImportMap = getImportMap(redBuild)
      const blueImportMap = getImportMap(blueBuild)
      const cssName = cssFileName.slice(0, -'.css'.length)
      const cssSpecifier = Object.keys(redImportMap).find(
        (specifier) =>
          specifier.includes(`/${cssName}-`) && specifier.endsWith('.css'),
      )!

      // The hash in the import map specifier is stable across builds,
      // but the mapped filename changes properly
      expect(cssSpecifier).toBeDefined()
      expect(redImportMap[cssSpecifier]).toBe(`/${getCssFileName(redBuild)}`)
      expect(blueImportMap[cssSpecifier]).toBe(`/${getCssFileName(blueBuild)}`)
      expect(redImportMap[cssSpecifier]).not.toBe(blueImportMap[cssSpecifier])
    },
  )
}


import fs from 'node:fs'
import path from 'node:path'
import { globSync } from 'tinyglobby'
import { normalizePath } from 'vite'
import postcssNested from 'postcss-nested'

export default {
  plugins: [
    postcssNested,
    testDirDep,
    testSourceInput,
    testInjectUrl,
    testInjectUrlOnceExit,
  ],
}

/**
 * A plugin for testing the `dir-dependency` message handling.
 */
function testDirDep() {
  return {
    postcssPlugin: 'dir-dep',
    AtRule(atRule, { result, Comment }) {
      if (atRule.name === 'test') {
        const pattern = normalizePath(
          path.resolve(path.dirname(result.opts.from), './glob-dep/**/*.css'),
        )
        const files = globSync(pattern, { expandDirectories: false })
        const text = files.map((f) => fs.readFileSync(f, 'utf-8')).join('\n')
        atRule.parent.insertAfter(atRule, text)
        atRule.remove()

        result.messages.push({
          type: 'dir-dependency',
          plugin: 'dir-dep',
          dir: './glob-dep',
          glob: '*.css',
          parent: result.opts.from,
        })

        result.messages.push({
          type: 'dir-dependency',
          plugin: 'dir-dep',
          dir: './glob-dep/nested (dir)', // includes special characters in glob
          glob: '*.css',
          parent: result.opts.from,
        })
      }
    },
  }
}
testDirDep.postcss = true

function testSourceInput() {
  return {
    postcssPlugin: 'source-input',
    AtRule(atRule) {
      if (atRule.name === 'source-input') {
        atRule.after(
          `.source-input::before { content: ${JSON.stringify(
            atRule.source.input.from,
          )}; }`,
        )
        atRule.remove()
      }
    },
  }
}
testSourceInput.postcss = true

function testInjectUrl() {
  return {
    postcssPlugin: 'inject-url',
    Once(root, { Rule }) {
      root.walkAtRules('inject-url', (atRule) => {
        const rule = new Rule({
          selector: '.inject-url',
          source: atRule.source,
        })
        rule.append({
          prop: 'background',
          value: "url('=/ok.png')",
          source: atRule.source,
        })
        atRule.after(rule)
        atRule.remove()
      })
    },
  }
}
testInjectUrl.postcss = true

/**
 * A plugin for testing url() rewriting in content injected at OnceExit with
 * its own source file (like postcss-modules inlining composed files)
 */
function testInjectUrlOnceExit() {
  return {
    postcssPlugin: 'inject-url-once-exit',
    OnceExit(root, { postcss }) {
      root.walkAtRules('inject-url-once-exit', (atRule) => {
        atRule.remove()
        root.prepend(
          postcss.parse(
            '.inject-url-once-exit { background: url(./injected-bg.png) }',
            {
              from: path.join(
                import.meta.dirname,
                'injected-source/injected.css',
              ),
            },
          ),
        )
      })
    },
  }
}
testInjectUrlOnceExit.postcss = true


import { defaultClientConditions, defineConfig } from 'vite'

export default defineConfig({
  build: {
    minify: false,
  },
  resolve: {
    dedupe: ['react'],
  },
  ssr: {
    target: 'webworker',
    noExternal: ['this-should-be-replaced-by-the-boolean'],
    // Some webworker builds may choose to externalize node builtins as they may be implemented
    // in the runtime, and so we can externalize it when bundling.
    external: ['node:assert'],
    resolve: {
      conditions: [...defaultClientConditions, 'worker'],
    },
  },
  plugins: [
    {
      name: '@vitejs/test-ssr-webworker/no-external',
      config() {
        return {
          ssr: {
            noExternal: true,
          },
        }
      },
    },
    {
      name: '@vitejs/test-ssr-webworker/no-external-array',
      config() {
        return {
          ssr: {
            noExternal: ['this-should-not-replace-the-boolean'],
          },
        }
      },
    },
  ],
})


#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main()
{
    // create a JSON array
    json v = {1, 2, 3, 4};

    // insert range from v2 before the end of array v
    auto new_pos = v.insert(v.end(), {7, 8, 9});

    // output new array and result of insert call
    std::cout << *new_pos << '\n';
    std::cout << v << '\n';
}


# <small>nlohmann::basic_json::</small>object

```cpp
static basic_json object(initializer_list_t init = {});
```

Creates a JSON object value from a given initializer list. The initializer lists elements must be pairs, and their first
elements must be strings. If the initializer list is empty, the empty object `#!json {}` is created.

## Parameters

`init` (in)
:   initializer list with JSON values to create an object from (optional)

## Return value

JSON object value

## Exception safety

Strong guarantee: if an exception is thrown, there are no changes in the JSON value.

## Exceptions

Throws [`type_error.301`](../../home/exceptions.md#jsonexceptiontype_error301) if `init` is not a list of pairs whose
first elements are strings. In this case, no object can be created. When such a value is passed to
`basic_json(initializer_list_t, bool, value_t)`, an array would have been created from the passed initializer list
`init`. See the example below.

## Complexity

Linear in the size of `init`.

## Notes

This function is only added for symmetry reasons. In contrast to the related function `array(initializer_list_t)`, there
are no cases that can only be expressed by this function. That is, any initializer list `init` can also be passed to
the initializer list constructor `basic_json(initializer_list_t, bool, value_t)`.

## Examples

??? example

    The following code shows an example for the `object` function.

    ```cpp
    --8<-- "examples/object.cpp"
    ```

    Output:

    ```json
    --8<-- "examples/object.output"
    ```

## See also

- [`basic_json(initializer_list_t)`](basic_json.md) - create a JSON value from an initializer list
- [`array`](array.md) - create a JSON array value from an initializer list
- [Creating JSON values](../../features/creating_values.md) - the article on creating JSON values

## Version history

- Added in version 1.0.0.


declare const __DEFINES__: Record<string, any>

const context = (() => {
  if (typeof globalThis !== 'undefined') {
    return globalThis
  } else if (typeof self !== 'undefined') {
    return self
  } else if (typeof window !== 'undefined') {
    return window
  } else {
    return Function('return this')()
  }
})()

// assign defines
const defines = __DEFINES__
Object.keys(defines).forEach((key) => {
  const segments = key.split('.')
  let target = context
  for (let i = 0; i < segments.length; i++) {
    const segment = segments[i]
    if (i === segments.length - 1) {
      target[segment] = defines[key]
    } else {
      target = target[segment] || (target[segment] = {})
    }
  }
})


import fs from 'node:fs'
import path from 'node:path'

// Notable dependencies to highlight (by package name)
const notableDependencies = [
  'rolldown',
  'postcss',
  'lightningcss',
  'chokidar',
  'magic-string',
]

// Dev tools used for development
const devToolNames = [
  'eslint',
  'prettier',
  'typescript',
  'vitest',
  'playwright-chromium',
]

// Past notable dependencies that Vite used previously
const pastNotableDependencies: PastDependency[] = [
  {
    name: 'esbuild',
    description:
      'JavaScript/TypeScript bundler and minifier (now using Rolldown, Oxc, and LightningCSS)',
    repository: 'https://github.com/evanw/esbuild',
  },
  {
    name: 'rollup',
    description: 'ES module bundler (now using Rolldown)',
    repository: 'https://github.com/rollup/rollup',
  },
  {
    name: 'http-proxy',
    description: 'HTTP proxying (now using http-proxy-3)',
    repository: 'https://github.com/http-party/node-http-proxy',
  },
  {
    name: 'acorn',
    description: 'JavaScript parser',
    repository: 'https://github.com/acornjs/acorn',
  },
  {
    name: 'fast-glob',
    description: 'Fast glob matching (now using tinyglobby/fdir)',
    repository: 'https://github.com/mrmlnc/fast-glob',
  },
  {
    name: 'debug',
    description: 'Debug logging (now using obug)',
    repository: 'https://github.com/debug-js/debug',
  },
]

const vitePackageDir = path.resolve(import.meta.dirname, '../../packages/vite')

interface PackageJson {
  name: string
  version: string
  description?: string
  author?: string | { name: string; email?: string; url?: string }
  repository?: string | { type?: string; url?: string }
  funding?:
    | string
    | { url: string; type?: string }
    | Array<string | { url: string; type?: string }>
  dependencies?: Record<string, string>
  devDependencies?: Record<string, string>
  optionalDependencies?: Record<string, string>
}

export interface Dependency {
  name: string
  version: string
  description?: string
  author?: string
  authorUrl?: string
  repository?: string
  funding?: string
}

export interface PastDependency {
  name: string
  description: string
  repository: string
}

export interface AuthorPackage {
  name: string
  funding?: string
}

export interface Author {
  name: string
  url?: string
  funding?: string
  packages: AuthorPackage[]
}

export interface AcknowledgementsData {
  bundledDependencies: Dependency[]
  notableDependencies: Dependency[]
  devTools: Dependency[]
  pastNotableDependencies: PastDependency[]
  authors: Author[]
}

/**
 * Parse the LICENSE.md file to extract bundled dependency names.
 */
function parseBundledDependenciesFromLicense(licensePath: string): string[] {
  const content = fs.readFileSync(licensePath, 'utf-8')

  // Find the "# Bundled dependencies:" section and parse package names from ## headers
  const bundledSection = content.split('# Bundled dependencies:\n')[1]
  if (!bundledSection) return []

  // Match all ## headers which contain package names (comma-separated for grouped packages)
  const deps = [...bundledSection.matchAll(/^## (.+)$/gm)].flatMap((m) =>
    // Package names can be comma-separated (e.g., "## pkg1, pkg2, pkg3")
    m[1].split(',').map((n) => n.trim()),
  )
  return [...new Set(deps)]
}

function normalizeRepository(
  repo: PackageJson['repository'],
): string | undefined {
  if (!repo) return undefined

  let url: string
  if (typeof repo === 'string') {
    url = repo
  } else if (repo.url) {
    url = repo.url
  } else {
    return undefined
  }
  url = url
    .replace(/^git\+/, '')
    .replace(/\.git$/, '')
    .replace(/(^|\/)[^/]+?@/, '$1') // remove "user@" from "ssh://user@host.com:..."
    .replace(/(\.[^.]+?):/, '$1/') // change ".com:" to ".com/" from "ssh://user@host.com:..."
    .replace(/^git:\/\//, 'https://')
    .replace(/^ssh:\/\//, 'https://')
  if (url.startsWith('github:')) {
    return `https://github.com/${url.slice(7)}`
  } else if (url.startsWith('gitlab:')) {
    return `https://gitlab.com/${url.slice(7)}`
  } else if (url.startsWith('bitbucket:')) {
    return `https://bitbucket.org/${url.slice(10)}`
  } else if (!url.includes(':') && url.split('/').length === 2) {
    return `https://github.com/${url}`
  } else {
    return url.includes('://') ? url : `https://${url}`
  }
}

function normalizeFunding(funding: PackageJson['funding']): string | undefined {
  if (!funding) return undefined
  if (typeof funding === 'string') return funding
  if (Array.isArray(funding)) {
    const first = funding[0]
    if (typeof first === 'string') return first
    return first?.url
  }
  return funding.url
}

function parseAuthor(author: PackageJson['author']): {
  name?: string
  url?: string
} {
  if (!author) return {}
  if (typeof author === 'object') {
    return { name: author.name, url: author.url }
  }
  // Parse string format: "Name <email> (url)" or "Name (url)" or "Name <email>" or "Name"
  let str = author
  let url: string | undefined
  const urlMatch = str.match(/\(([^)]+)\)$/)
  if (urlMatch) {
    url = urlMatch[1]
    str = str.slice(0, urlMatch.index).trim()
  }
  const emailIndex = str.indexOf('<')
  if (emailIndex !== -1) {
    str = str.slice(0, emailIndex).trim()
  }
  return { name: str || author, url }
}

function readPackageInfo(
  packageName: string,
  nodeModulesDir: string,
): Dependency | null {
  const packagePath = path.join(nodeModulesDir, packageName, 'package.json')

  try {
    const content = fs.readFileSync(packagePath, 'utf-8')
    const pkg: PackageJson = JSON.parse(content)
    const authorInfo = parseAuthor(pkg.author)

    return {
      name: pkg.name,
      version: pkg.version,
      description: pkg.description,
      author: authorInfo.name,
      authorUrl: authorInfo.url,
      repository: normalizeRepository(pkg.repository),
      funding: normalizeFunding(pkg.funding),
    }
  } catch {
    // Package might not exist in node_modules (optional peer dep, etc.)
    return null
  }
}

function groupByAuthor(dependencies: Dependency[]): Author[] {
  const authorMap = new Map<
    string,
    { url?: string; packages: AuthorPackage[] }
  >()

  for (const dep of dependencies) {
    if (dep.author) {
      const existing = authorMap.get(dep.author)
      if (existing) {
        existing.packages.push({ name: dep.name, funding: dep.funding })
        if (!existing.url && dep.authorUrl) {
          existing.url = dep.authorUrl
        }
      } else {
        authorMap.set(dep.author, {
          url: dep.authorUrl,
          packages: [{ name: dep.name, funding: dep.funding }],
        })
      }
    }
  }

  return Array.from(authorMap.entries())
    .map(([name, info]) => {
      const sortedPackages = info.packages.sort((a, b) =>
        a.name.localeCompare(b.name),
      )
      const fundingUrls = new Set(
        sortedPackages.map((p) => p.funding).filter(Boolean),
      )
      const sharedFunding =
        fundingUrls.size === 1 ? [...fundingUrls][0] : undefined
      return {
        name,
        url: info.url,
        funding: sharedFunding,
        packages: sharedFunding
          ? sortedPackages.map((p) => ({ name: p.name }))
          : sortedPackages,
      }
    })
    .sort((a, b) => a.name.localeCompare(b.name))
}

function loadData(): AcknowledgementsData {
  const licensePath = path.join(vitePackageDir, 'LICENSE.md')
  const nodeModulesDir = path.join(vitePackageDir, 'node_modules')
  const rootNodeModulesDir = path.resolve(
    import.meta.dirname,
    '../../node_modules',
  )

  const bundledDepNames = parseBundledDependenciesFromLicense(licensePath)
  const bundledDependencies = bundledDepNames
    .map(
      (name) =>
        readPackageInfo(name, nodeModulesDir) ||
        readPackageInfo(name, rootNodeModulesDir),
    )
    .filter((dep) => dep != null)
    .sort((a, b) => a.name.localeCompare(b.name))

  const devTools = devToolNames
    .map((name) => readPackageInfo(name, rootNodeModulesDir))
    .filter((dep) => dep != null)
    .sort((a, b) => a.name.localeCompare(b.name))

  const notableDeps = notableDependencies
    .map(
      (name) =>
        readPackageInfo(name, nodeModulesDir) ||
        readPackageInfo(name, rootNodeModulesDir),
    )
    .filter((dep) => dep != null)

  const nonNotableDeps = bundledDependencies.filter(
    (d) => !notableDependencies.includes(d.name),
  )

  return {
    bundledDependencies,
    notableDependencies: notableDeps,
    devTools,
    pastNotableDependencies,
    authors: groupByAuthor(nonNotableDeps),
  }
}

// Export data for VitePress
declare const data: AcknowledgementsData
export { data }

export default {
  watch: ['../../packages/vite/LICENSE.md'],
  load(): AcknowledgementsData {
    return loadData()
  },
}


//! Deserialization for internally tagged enums:
//!
//! ```ignore
//! #[serde(tag = "...")]
//! enum Enum {}
//! ```

use crate::de::enum_;
use crate::de::enum_untagged;
use crate::de::struct_;
use crate::de::{
    effective_style, expr_is_missing, field_i, unwrap_to_variant_closure, Parameters, StructForm,
};
use crate::fragment::{Expr, Fragment, Match};
use crate::internals::ast::{Style, Variant};
use crate::internals::attr;
use crate::private;
use quote::quote;

/// Generates `Deserialize::deserialize` body for an `enum Enum {...}` with `#[serde(tag)]` attribute
pub(super) fn deserialize(
    params: &Parameters,
    variants: &[Variant],
    cattrs: &attr::Container,
    tag: &str,
) -> Fragment {
    let (variants_stmt, variant_visitor) = enum_::prepare_enum_variant_enum(variants);

    // Match arms to extract a variant from a string
    let variant_arms = variants
        .iter()
        .enumerate()
        .filter(|&(_, variant)| !variant.attrs.skip_deserializing())
        .map(|(i, variant)| {
            let variant_name = field_i(i);

            let block = Match(deserialize_internally_tagged_variant(
                params, variant, cattrs,
            ));

            quote! {
                __Field::#variant_name => #block
            }
        });

    let expecting = format!("internally tagged enum {}", params.type_name());
    let expecting = cattrs.expecting().unwrap_or(&expecting);

    quote_block! {
        #variant_visitor

        #variants_stmt

        let (__tag, __content) = _serde::Deserializer::deserialize_any(
            __deserializer,
            _serde::#private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting))?;
        let __deserializer = _serde::#private::de::ContentDeserializer::<__D::Error>::new(__content);

        match __tag {
            #(#variant_arms)*
        }
    }
}

// Generates significant part of the visit_seq and visit_map bodies of visitors
// for the variants of internally tagged enum.
fn deserialize_internally_tagged_variant(
    params: &Parameters,
    variant: &Variant,
    cattrs: &attr::Container,
) -> Fragment {
    if let Some(path) = variant.attrs.deserialize_with() {
        let unwrap_fn = unwrap_to_variant_closure(params, variant, false);
        return quote_block! {
            _serde::#private::Result::map(#path(__deserializer), #unwrap_fn)
        };
    }

    let variant_ident = &variant.ident;

    match effective_style(variant) {
        Style::Unit => {
            let this_value = &params.this_value;
            let type_name = params.type_name();
            let variant_name = variant.ident.to_string();
            let default = variant.fields.first().map(|field| {
                let default = Expr(expr_is_missing(field, cattrs));
                quote!((#default))
            });
            quote_block! {
                _serde::Deserializer::deserialize_any(__deserializer, _serde::#private::de::InternallyTaggedUnitVisitor::new(#type_name, #variant_name))?;
                _serde::#private::Ok(#this_value::#variant_ident #default)
            }
        }
        Style::Newtype => {
            enum_untagged::deserialize_newtype_variant(variant_ident, params, &variant.fields[0])
        }
        Style::Struct => struct_::deserialize(
            params,
            &variant.fields,
            cattrs,
            StructForm::InternallyTagged(variant_ident),
        ),
        Style::Tuple => unreachable!("checked in serde_derive_internals"),
    }
}


# <small>nlohmann::basic_json::</small>from_bson

```cpp
// (1)
template<typename InputType>
static basic_json from_bson(InputType&& i,
                            const bool strict = true,
                            const bool allow_exceptions = true);
// (2)
template<typename IteratorType, typename SentinelType = IteratorType>
static basic_json from_bson(IteratorType first, SentinelType last,
                            const bool strict = true,
                            const bool allow_exceptions = true);
```

Deserializes a given input to a JSON value using the BSON (Binary JSON) serialization format.

1. Reads from a compatible input.
2. Reads from an iterator range, or an iterator and a sentinel of a different type (C++20 ranges support).

The exact mapping and its limitations are described on a [dedicated page](../../features/binary_formats/bson.md).

## Template parameters

`InputType`
:   A compatible input, for instance:

    - an `std::istream` object
    - a `FILE` pointer
    - a C-style array of characters
    - a pointer to a null-terminated string of single byte characters
    - a container `obj` for which `begin(obj)` and `end(obj)` produce a valid pair of iterators
      (as found via ADL or member functions, with semantics compatible to `std::begin` and `std::end`)

`IteratorType`
:   a compatible iterator type

`SentinelType`
:   defaults to `IteratorType`; may be a different type comparable to `IteratorType` via `operator!=`, for instance.

    - a custom sentinel type for C++20 ranges
    - `std::default_sentinel_t`, when `IteratorType` is `std::counted_iterator`

## Parameters

`i` (in)
:   an input in BSON format convertible to an input adapter

`first` (in)
:   iterator to the start of the input

`last` (in)
:   iterator to the end of the input, or a sentinel value that compares equal to the end iterator with `operator!=`

`strict` (in)
:   whether to expect the input to be consumed until EOF (`#!cpp true` by default)

`allow_exceptions` (in)
:   whether to throw exceptions in case of a parse error (optional, `#!cpp true` by default)

## Return value

deserialized JSON value; in case of a parse error and `allow_exceptions` set to `#!cpp false`, the return value will be
`value_t::discarded`.  The latter can be checked with [`is_discarded`](is_discarded.md).

## Exception safety

Strong guarantee: if an exception is thrown, there are no changes in the JSON value.

## Exceptions

- Throws [`parse_error.110`](../../home/exceptions.md#jsonexceptionparse_error110) if the given input ends prematurely or
  the end of the input was not reached when `strict` was set to true
- Throws [`parse_error.112`](../../home/exceptions.md#jsonexceptionparse_error112) if a parse error occurs (e.g., an
  invalid string or byte array length)
- Throws [`parse_error.114`](../../home/exceptions.md#jsonexceptionparse_error114) if an unsupported BSON record type is
  encountered

## Complexity

Linear in the size of the input.

## Examples

??? example

    The example shows the deserialization of a byte vector in BSON format to a JSON value.

    ```cpp
    --8<-- "examples/from_bson.cpp"
    ```

    Output:

    ```json
    --8<-- "examples/from_bson.output"
    ```

## See also

- [BSON specification](http://bsonspec.org/spec.html)
- [to_bson](to_bson.md) for the analogous serialization
- [from_cbor](from_cbor.md) for the related CBOR format
- [from_msgpack](from_msgpack.md) for the related MessagePack format
- [from_ubjson](from_ubjson.md) for the related UBJSON format
- [from_bjdata](from_bjdata.md) for the related BJData format

## Version history

- Added in version 3.4.0.
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.

!!! warning "Deprecation"

    - Overload (2) replaces calls to `from_bson` with a pointer and a length as first two parameters, which has been
      deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
      `#!cpp from_bson(ptr, len, ...);` with `#!cpp from_bson(ptr, ptr+len, ...);`.
    - Overload (2) replaces calls to `from_bson` with a pair of iterators as their first parameter, which has been
      deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
      `#!cpp from_bson({ptr, ptr+len}, ...);` with `#!cpp from_bson(ptr, ptr+len, ...);`.

    You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated
    function.


// no `exports` key, should resolve to entries/dir/index.js
import dirEntry from '@vitejs/test-entries/dir'
// no `exports` key, should resolve to entries/file.js
import fileEntry from '@vitejs/test-entries/file'
// has `exports` key, should resolve to pkg-exports/entry
import pkgExportsEntry from '@vitejs/test-resolve-pkg-exports/entry'
import deepFoo from '@vitejs/test-deep-import/foo'
// import deepBar from '@vitejs/test-deep-import/bar'
import moduleSync from '@vitejs/test-module-sync'
import { used } from './util'

export default `
  entries/dir: ${dirEntry}
  entries/file: ${fileEntry}
  pkg-exports/entry: ${pkgExportsEntry}
  deep-import/foo: ${deepFoo}
  ${/* `deep-import/bar: ${deepBar}` */ ''}
  module-sync: ${moduleSync}
  util: ${used(['[success]'])}
`


//     __ _____ _____ _____
//  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
// |  |  |__   |  |  | | | |  version 3.12.0
// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT

// cmake/test.cmake selects the C++ standard versions with which to build a
// unit test based on the presence of JSON_HAS_CPP_<VERSION> macros.
// When using macros that are only defined for particular versions of the standard
// (e.g., JSON_HAS_FILESYSTEM for C++17 and up), please mention the corresponding
// version macro in a comment close by, like this:
// JSON_HAS_CPP_<VERSION> (do not remove; see note at top of file)

#include "doctest_compatibility.h"

// for some reason including this after the json header leads to linker errors with VS 2017...
#include <locale>

#define JSON_TESTS_PRIVATE
#include <nlohmann/json.hpp>
using json = nlohmann::json;
using ordered_json = nlohmann::ordered_json;
#ifdef JSON_TEST_NO_GLOBAL_UDLS
    using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
#endif

#include <cstdio>
#include <list>
#include <type_traits>
#include <utility>

#ifdef JSON_HAS_CPP_17
    #include <any>
    #include <variant>
#endif

#ifdef JSON_HAS_CPP_17
    #if __has_include(<optional>)
        #include <optional>
    #elif __has_include(<experimental/optional>)
        #include <experimental/optional>
    #endif

    /////////////////////////////////////////////////////////////////////
    // for #4804
    /////////////////////////////////////////////////////////////////////
    using json_4804 = nlohmann::basic_json<std::map,        // ObjectType
    std::vector,     // ArrayType
    std::string,     // StringType
    bool,            // BooleanType
    std::int64_t,    // NumberIntegerType
    std::uint64_t,   // NumberUnsignedType
    double,          // NumberFloatType
    std::allocator,  // AllocatorType
    nlohmann::adl_serializer,  // JSONSerializer
    std::vector<std::byte>,    // BinaryType
    void                       // CustomBaseClass
    >;
#endif

#ifdef JSON_HAS_CPP_20
    #if __has_include(<span>)
        #include <span>
    #endif
#endif

/////////////////////////////////////////////////////////////////////
// for #4825 - explicitly instantiating basic_json must compile; this
// forces instantiation of binary_writer::write_bjdata_ndarray, whose
// static_cast<string_t> was ambiguous under explicit instantiation on
// C++17. Merely compiling this translation unit is the regression test.
/////////////////////////////////////////////////////////////////////
template class nlohmann::basic_json<>;

/////////////////////////////////////////////////////////////////////
// for #4440
/////////////////////////////////////////////////////////////////////
#if JSON_HAS_RANGES == 1
    #include <ranges>
#endif

// NLOHMANN_JSON_SERIALIZE_ENUM uses a static std::pair
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")

/////////////////////////////////////////////////////////////////////
// for #1021
/////////////////////////////////////////////////////////////////////

using float_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, float>;

/////////////////////////////////////////////////////////////////////
// for #1647
/////////////////////////////////////////////////////////////////////
namespace
{
struct NonDefaultFromJsonStruct
{};

inline bool operator==(NonDefaultFromJsonStruct const& /*unused*/, NonDefaultFromJsonStruct const& /*unused*/)
{
    return true;
}

enum class for_1647
{
    one,
    two
};

// NOLINTNEXTLINE(misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): this is a false positive
NLOHMANN_JSON_SERIALIZE_ENUM(for_1647,
{
    {for_1647::one, "one"},
    {for_1647::two, "two"},
})
}  // namespace

/////////////////////////////////////////////////////////////////////
// for #1299
/////////////////////////////////////////////////////////////////////

struct Data
{
    Data() = default;
    Data(std::string a_, std::string b_)
        : a(std::move(a_))
        , b(std::move(b_))
    {}
    std::string a{}; // NOLINT(readability-redundant-member-init)
    std::string b{}; // NOLINT(readability-redundant-member-init)
};

void from_json(const json& j, Data& data); // NOLINT(misc-use-internal-linkage)
void from_json(const json& j, Data& data)
{
    j["a"].get_to(data.a);
    j["b"].get_to(data.b);
}

bool operator==(Data const& lhs, Data const& rhs); // NOLINT(misc-use-internal-linkage)
bool operator==(Data const& lhs, Data const& rhs)
{
    return lhs.a == rhs.a && lhs.b == rhs.b;
}

//bool operator!=(Data const& lhs, Data const& rhs)
//{
//    return !(lhs == rhs);
//}

namespace nlohmann
{
template<>
struct adl_serializer<NonDefaultFromJsonStruct>
{
    static NonDefaultFromJsonStruct from_json(json const& /*unused*/) noexcept
    {
        return {};
    }
};
}  // namespace nlohmann

/////////////////////////////////////////////////////////////////////
// for #1805
/////////////////////////////////////////////////////////////////////

struct NotSerializableData
{
    int mydata;
    float myfloat;
};

/////////////////////////////////////////////////////////////////////
// for #2574
/////////////////////////////////////////////////////////////////////

struct NonDefaultConstructible
{
    explicit NonDefaultConstructible(int a)
        : x(a)
    {}
    int x;
};

namespace nlohmann
{
template<>
struct adl_serializer<NonDefaultConstructible>
{
    static NonDefaultConstructible from_json(json const& j)
    {
        return NonDefaultConstructible(j.get<int>());
    }
};
}  // namespace nlohmann

/////////////////////////////////////////////////////////////////////
// for #2824
/////////////////////////////////////////////////////////////////////

class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json, nlohmann::detail::string_input_adapter_type>
{
  public:
    explicit sax_no_exception(json& j)
        : nlohmann::detail::json_sax_dom_parser<json, nlohmann::detail::string_input_adapter_type>(j, false)
    {}

    static bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex)
    {
        error_string = new std::string(ex.what());  // NOLINT(cppcoreguidelines-owning-memory)
        return false;
    }

    static std::string* error_string;
};

std::string* sax_no_exception::error_string = nullptr;

/////////////////////////////////////////////////////////////////////
// for #2982
/////////////////////////////////////////////////////////////////////

template<class T>
class my_allocator : public std::allocator<T>
{
  public:
    using std::allocator<T>::allocator;

    my_allocator() = default;
    template<class U> my_allocator(const my_allocator<U>& /*unused*/) { }

    template <class U>
    struct rebind
    {
        using other = my_allocator<U>;
    };
};

/////////////////////////////////////////////////////////////////////
// for #3077
/////////////////////////////////////////////////////////////////////

class FooAlloc
{};

class Foo
{
  public:
    explicit Foo(const FooAlloc& /* unused */ = FooAlloc()) {}

    bool value = false;
};

class FooBar
{
  public:
    Foo foo{}; // NOLINT(readability-redundant-member-init)
};

inline void from_json(const nlohmann::json& j, FooBar& fb) // NOLINT(misc-use-internal-linkage)
{
    j.at("value").get_to(fb.foo.value);
}

/////////////////////////////////////////////////////////////////////
// for #3171
/////////////////////////////////////////////////////////////////////

struct for_3171_base // NOLINT(cppcoreguidelines-special-member-functions)
{
    for_3171_base(const std::string& /*unused*/ = {}) {}
    virtual ~for_3171_base();

    for_3171_base(const for_3171_base& other) // NOLINT(hicpp-use-equals-default,modernize-use-equals-default)
        : str(other.str)
    {}

    for_3171_base& operator=(const for_3171_base& other)
    {
        if (this != &other)
        {
            str = other.str;
        }
        return *this;
    }

    for_3171_base(for_3171_base&& other) noexcept
        : str(std::move(other.str))
    {}

    for_3171_base& operator=(for_3171_base&& other) noexcept
    {
        if (this != &other)
        {
            str = std::move(other.str);
        }
        return *this;
    }

    virtual void _from_json(const json& j)
    {
        j.at("str").get_to(str);
    }

    std::string str{}; // NOLINT(readability-redundant-member-init)
};

for_3171_base::~for_3171_base() = default;

struct for_3171_derived : public for_3171_base
{
    for_3171_derived() = default;
    ~for_3171_derived() override;
    explicit for_3171_derived(const std::string& /*unused*/) { }

    for_3171_derived(const for_3171_derived& other) // NOLINT(hicpp-use-equals-default,modernize-use-equals-default)
        : for_3171_base(other)
    {}

    for_3171_derived& operator=(const for_3171_derived& other)
    {
        if (this != &other)
        {
            for_3171_base::operator=(other); // Call base class assignment operator
        }
        return *this;
    }

    for_3171_derived(for_3171_derived&& other) noexcept
        : for_3171_base(std::move(other))
    {}

    for_3171_derived& operator=(for_3171_derived&& other) noexcept
    {
        if (this != &other)
        {
            for_3171_base::operator=(std::move(other)); // Call base class move assignment operator
        }
        return *this;
    }
};

for_3171_derived::~for_3171_derived() = default;

inline void from_json(const json& j, for_3171_base& tb) // NOLINT(misc-use-internal-linkage)
{
    tb._from_json(j);
}

/////////////////////////////////////////////////////////////////////
// for #3312
/////////////////////////////////////////////////////////////////////

#ifdef JSON_HAS_CPP_20
struct for_3312
{
    std::string name;
};

inline void from_json(const json& j, for_3312& obj) // NOLINT(misc-use-internal-linkage)
{
    j.at("name").get_to(obj.name);
}
#endif

/////////////////////////////////////////////////////////////////////
// for #3204
/////////////////////////////////////////////////////////////////////

struct for_3204_foo
{
    for_3204_foo() = default;
    explicit for_3204_foo(std::string /*unused*/) {} // NOLINT(performance-unnecessary-value-param)
};

struct for_3204_bar
{
    enum constructed_from_t // NOLINT(cppcoreguidelines-use-enum-class)
    {
        constructed_from_none = 0,
        constructed_from_foo = 1,
        constructed_from_json = 2
    };

    explicit for_3204_bar(std::function<void(for_3204_foo)> /*unused*/) noexcept // NOLINT(performance-unnecessary-value-param)
        : constructed_from(constructed_from_foo) {}
    explicit for_3204_bar(std::function<void(json)> /*unused*/) noexcept // NOLINT(performance-unnecessary-value-param)
        : constructed_from(constructed_from_json) {}

    constructed_from_t constructed_from = constructed_from_none;
};

/////////////////////////////////////////////////////////////////////
// for #3333
/////////////////////////////////////////////////////////////////////

struct for_3333 final
{
    for_3333(int x_ = 0, int y_ = 0) : x(x_), y(y_) {}

    template <class T>
    for_3333(const T& /*unused*/)
    {
        CHECK(false);
    }

    int x = 0;
    int y = 0;
};

template <>
inline for_3333::for_3333(const json& j)
    : for_3333(j.value("x", 0), j.value("y", 0))
{}

/////////////////////////////////////////////////////////////////////
// for #3810
/////////////////////////////////////////////////////////////////////

struct Example_3810
{
    int bla{};

    Example_3810() = default;
};

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Example_3810, bla) // NOLINT(misc-use-internal-linkage)

/////////////////////////////////////////////////////////////////////
// for #4740
/////////////////////////////////////////////////////////////////////

#ifdef JSON_HAS_CPP_17
struct Example_4740
{
    std::optional<std::string> host = std::nullopt;
    std::optional<int> port = std::nullopt;
    NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Example_4740, host, port)
};
#endif

TEST_CASE("regression tests 2")
{
    SECTION("issue #1001 - Fix memory leak during parser callback")
    {
        const auto* geojsonExample = R"(
          { "type": "FeatureCollection",
            "features": [
              { "type": "Feature",
                "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},
                "properties": {"prop0": "value0"}
                },
              { "type": "Feature",
                "geometry": {
                  "type": "LineString",
                  "coordinates": [
                    [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]
                    ]
                  },
                "properties": {
                  "prop0": "value0",
                  "prop1": 0.0
                  }
                },
              { "type": "Feature",
                 "geometry": {
                   "type": "Polygon",
                   "coordinates": [
                     [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
                       [100.0, 1.0], [100.0, 0.0] ]
                     ]
                 },
                 "properties": {
                   "prop0": "value0",
                   "prop1": {"this": "that"}
                   }
                 }
               ]
             })";

        const json::parser_callback_t cb = [&](int /*level*/, json::parse_event_t event, json & parsed) noexcept
        {
            // skip uninteresting events
            if (event == json::parse_event_t::value && !parsed.is_primitive())
            {
                return false;
            }

            switch (event)
            {
                case json::parse_event_t::key:
                {
                    return true;
                }
                case json::parse_event_t::value:
                {
                    return false;
                }
                case json::parse_event_t::object_start:
                {
                    return true;
                }
                case json::parse_event_t::object_end:
                {
                    return false;
                }
                case json::parse_event_t::array_start:
                {
                    return true;
                }
                case json::parse_event_t::array_end:
                {
                    return false;
                }

                default:
                {
                    return true;
                }
            }
        };

        auto j = json::parse(geojsonExample, cb, true);
        CHECK(j == json());
    }

    SECTION("issue #1021 - to/from_msgpack only works with standard typization")
    {
        float_json j = 1000.0;
        CHECK(float_json::from_cbor(float_json::to_cbor(j)) == j);
        CHECK(float_json::from_msgpack(float_json::to_msgpack(j)) == j);
        CHECK(float_json::from_ubjson(float_json::to_ubjson(j)) == j);

        float_json j2 = {1000.0, 2000.0, 3000.0};
        CHECK(float_json::from_ubjson(float_json::to_ubjson(j2, true, true)) == j2);
    }

    SECTION("issue #1045 - Using STL algorithms with JSON containers with expected results?")
    {
        json diffs = nlohmann::json::array();
        json m1{{"key1", 42}};
        json m2{{"key2", 42}};
        auto p1 = m1.items();
        auto p2 = m2.items();

        using it_type = decltype(p1.begin());

        std::set_difference(
            p1.begin(),
            p1.end(),
            p2.begin(),
            p2.end(),
            std::inserter(diffs, diffs.end()),
            [&](const it_type & e1, const it_type & e2) -> bool
        {
            using comper_pair = std::pair<std::string, decltype(e1.value())>;              // Trying to avoid unneeded copy
            return comper_pair(e1.key(), e1.value()) < comper_pair(e2.key(), e2.value());  // Using pair comper
        });

        CHECK(diffs.size() == 1);  // Note the change here, was 2
    }

#ifdef JSON_HAS_CPP_17
    SECTION("issue #1292 - Serializing std::variant causes stack overflow")
    {
        static_assert(!std::is_constructible<json, std::variant<int, float>>::value, "unexpected value");
    }
#endif

    SECTION("issue #1299 - compile error in from_json converting to container "
            "with std::pair")
    {
        const json j =
        {
            {"1", {{"a", "testa_1"}, {"b", "testb_1"}}},
            {"2", {{"a", "testa_2"}, {"b", "testb_2"}}},
            {"3", {{"a", "testa_3"}, {"b", "testb_3"}}},
        };

        const std::map<std::string, Data> expected
        {
            {"1", {"testa_1", "testb_1"}},
            {"2", {"testa_2", "testb_2"}},
            {"3", {"testa_3", "testb_3"}},
        };
        const auto data = j.get<decltype(expected)>();
        CHECK(expected == data);
    }

    SECTION("issue #1445 - buffer overflow in dumping invalid utf-8 strings")
    {
        SECTION("a bunch of -1, ensure_ascii=true")
        {
            const auto length = 300;

            json dump_test;
            dump_test["1"] = std::string(length, static_cast<std::string::value_type>(-1));

            std::string expected = R"({"1":")";
            for (int i = 0; i < length; ++i)
            {
                expected += "\\ufffd";
            }
            expected += "\"}";

            auto s = dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
            CHECK(s == expected);
        }
        SECTION("a bunch of -2, ensure_ascii=false")
        {
            const auto length = 500;

            json dump_test;
            dump_test["1"] = std::string(length, static_cast<std::string::value_type>(-2));

            std::string expected = R"({"1":")";
            for (int i = 0; i < length; ++i)
            {
                expected += "\xEF\xBF\xBD";
            }
            expected += "\"}";

            auto s = dump_test.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
            CHECK(s == expected);
        }
        SECTION("test case in issue #1445")
        {
            nlohmann::json dump_test;
            const std::array<int, 108> data =
            {
                {109, 108, 103, 125, -122, -53, 115, 18, 3, 0, 102, 19, 1, 15, -110, 13, -3, -1, -81, 32, 2, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -80, 2, 0, 0, 96, -118, 46, -116, 46, 109, -84, -87, 108, 14, 109, -24, -83, 13, -18, -51, -83, -52, -115, 14, 6, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 3, 0, 0, 0, 35, -74, -73, 55, 57, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, -96, -54, -28, -26}
            };
            std::string s;
            for (const int i : data)
            {
                s += static_cast<char>(i);
            }
            dump_test["1"] = s;
            dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
        }
    }

    SECTION("issue #1447 - Integer Overflow (OSS-Fuzz 12506)")
    {
        const json j = json::parse("[-9223372036854775808]");
        CHECK(j.dump() == "[-9223372036854775808]");
    }

    SECTION("issue #1708 - minimum value of int64_t can be outputted")
    {
        constexpr auto smallest = (std::numeric_limits<int64_t>::min)();
        const json j = smallest;
        CHECK(j.dump() == std::to_string(smallest));
    }

    SECTION("issue #1727 - Contains with non-const lvalue json_pointer picks the wrong overload")
    {
        const json j = {{"root", {{"settings", {{"logging", true}}}}}};

        auto jptr1 = "/root/settings/logging"_json_pointer;
        auto jptr2 = json::json_pointer{"/root/settings/logging"};

        CHECK(j.contains(jptr1));
        CHECK(j.contains(jptr2));
    }

    SECTION("issue #1647 - compile error when deserializing enum if both non-default from_json and non-member operator== exists for other type")
    {
        // does not compile on ICPC when targeting C++20
#if !(defined(__INTEL_COMPILER) && __cplusplus >= 202000)
        {
            const json j;
            const NonDefaultFromJsonStruct x(j);
            NonDefaultFromJsonStruct y;
            CHECK(x == y);
        }
#endif

        auto val = nlohmann::json("one").get<for_1647>();
        CHECK(val == for_1647::one);
        const json j = val;
    }

    SECTION("issue #1715 - json::from_cbor does not respect allow_exceptions = false when input is string literal")
    {
        SECTION("string literal")
        {
            const json cbor = json::from_cbor("B", true, false);
            CHECK(cbor.is_discarded());
        }

        SECTION("string array")
        {
            const std::array<char, 2> input = {{'B', 0x00}};
            const json cbor = json::from_cbor(input, true, false);
            CHECK(cbor.is_discarded());
        }

        SECTION("std::string")
        {
            const json cbor = json::from_cbor(std::string("B"), true, false);
            CHECK(cbor.is_discarded());
        }
    }

    SECTION("issue #1805 - A pair<T1, T2> is json constructible only if T1 and T2 are json constructible")
    {
        static_assert(!std::is_constructible<json, std::pair<std::string, NotSerializableData>>::value, "unexpected result");
        static_assert(!std::is_constructible<json, std::pair<NotSerializableData, std::string>>::value, "unexpected result");
        static_assert(std::is_constructible<json, std::pair<int, std::string>>::value, "unexpected result");
    }
    SECTION("issue #1825 - A tuple<Args..> is json constructible only if all T in Args are json constructible")
    {
        static_assert(!std::is_constructible<json, std::tuple<std::string, NotSerializableData>>::value, "unexpected result");
        static_assert(!std::is_constructible<json, std::tuple<NotSerializableData, std::string>>::value, "unexpected result");
        static_assert(std::is_constructible<json, std::tuple<int, std::string>>::value, "unexpected result");
    }

    SECTION("issue #1983 - JSON patch diff for op=add formation is not as per standard (RFC 6902)")
    {
        const auto source = R"({ "foo": [ "1", "2" ] })"_json;
        const auto target = R"({"foo": [ "1", "2", "3" ]})"_json;
        const auto result = json::diff(source, target);
        CHECK(result.dump() == R"([{"op":"add","path":"/foo/-","value":"3"}])");
    }

    SECTION("issue #2067 - cannot serialize binary data to text JSON")
    {
        const std::array<unsigned char, 23> data = {{0x81, 0xA4, 0x64, 0x61, 0x74, 0x61, 0xC4, 0x0F, 0x33, 0x30, 0x30, 0x32, 0x33, 0x34, 0x30, 0x31, 0x30, 0x37, 0x30, 0x35, 0x30, 0x31, 0x30}};
        const json j = json::from_msgpack(data.data(), data.size());
        CHECK_NOTHROW(
            j.dump(4,                             // Indent
                   ' ',                           // Indent char
                   false,                         // Ensure ascii
                   json::error_handler_t::strict  // Error
                  ));
    }

    SECTION("PR #2181 - regression bug with lvalue")
    {
        // see https://github.com/nlohmann/json/pull/2181#issuecomment-653326060
        const json j{{"x", "test"}};
        const std::string defval = "default value";
        auto val = j.value("x", defval); // NOLINT(bugprone-unused-local-non-trivial-variable)
        auto val2 = j.value("y", defval); // NOLINT(bugprone-unused-local-non-trivial-variable)
    }

    SECTION("issue #2293 - eof doesn't cause parsing to stop")
    {
        const std::vector<uint8_t> data =
        {
            0x7B,
            0x6F,
            0x62,
            0x6A,
            0x65,
            0x63,
            0x74,
            0x20,
            0x4F,
            0x42
        };
        const json result = json::from_cbor(data, true, false);
        CHECK(result.is_discarded());
    }

    SECTION("issue #2315 - json.update and vector<pair>does not work with ordered_json")
    {
        nlohmann::ordered_json jsonAnimals = {{"animal", "dog"}};
        const nlohmann::ordered_json jsonCat = {{"animal", "cat"}};
        jsonAnimals.update(jsonCat);
        CHECK(jsonAnimals["animal"] == "cat");

        auto jsonAnimals_parsed = nlohmann::ordered_json::parse(jsonAnimals.dump());
        CHECK(jsonAnimals == jsonAnimals_parsed);

        const std::vector<std::pair<std::string, int64_t>> intData = {std::make_pair("aaaa", 11),
                                                                      std::make_pair("bbb", 222)
                                                                     };
        nlohmann::ordered_json jsonObj;
        for (const auto& data : intData)
        {
            jsonObj[data.first] = data.second;
        }
        CHECK(jsonObj["aaaa"] == 11);
        CHECK(jsonObj["bbb"] == 222);
    }

    SECTION("issue #2330 - ignore_comment=true fails on multiple consecutive lines starting with comments")
    {
        const std::string ss = "//\n//\n{\n}\n";
        const json j = json::parse(ss, nullptr, true, true);
        CHECK(j.dump() == "{}");
    }

#ifdef JSON_HAS_CPP_20
#ifndef _LIBCPP_VERSION // see https://github.com/nlohmann/json/issues/4490
    // classic Intel ICC reports <span> as includable but cannot actually compile
    // std::span/std::as_bytes usage below
#if __has_include(<span>) && !defined(__ICC) && !defined(__INTEL_COMPILER)
    SECTION("issue #2546 - parsing containers of std::byte")
    {
        const char DATA[] = R"("Hello, world!")"; // NOLINT(misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
        const auto s = std::as_bytes(std::span(DATA));
        const json j = json::parse(s);
        CHECK(j.dump() == "\"Hello, world!\"");
    }
#endif
#endif
#endif

    SECTION("issue #2574 - Deserialization to std::array, std::pair, and std::tuple with non-default constructable types fails")
    {
        SECTION("std::array")
        {
            {
                const json j = {7, 4};
                auto arr = j.get<std::array<NonDefaultConstructible, 2>>();
                CHECK(arr[0].x == 7);
                CHECK(arr[1].x == 4);
            }

            {
                const json j = 7;
                CHECK_THROWS_AS((j.get<std::array<NonDefaultConstructible, 1>>()), json::type_error);
            }
        }

        SECTION("std::pair")
        {
            {
                const json j = {3, 8};
                auto p = j.get<std::pair<NonDefaultConstructible, NonDefaultConstructible>>();
                CHECK(p.first.x == 3);
                CHECK(p.second.x == 8);
            }

            {
                const json j = {4, 1};
                auto p = j.get<std::pair<int, NonDefaultConstructible>>();
                CHECK(p.first == 4);
                CHECK(p.second.x == 1);
            }

            {
                const json j = {6, 7};
                auto p = j.get<std::pair<NonDefaultConstructible, int>>();
                CHECK(p.first.x == 6);
                CHECK(p.second == 7);
            }

            {
                const json j = 7;
                CHECK_THROWS_AS((j.get<std::pair<NonDefaultConstructible, int>>()), json::type_error);
            }
        }

        SECTION("std::tuple")
        {
            {
                const json j = {9};
                auto t = j.get<std::tuple<NonDefaultConstructible>>();
                CHECK(std::get<0>(t).x == 9);
            }

            {
                const json j = {9, 8, 7};
                auto t = j.get<std::tuple<NonDefaultConstructible, int, NonDefaultConstructible>>();
                CHECK(std::get<0>(t).x == 9);
                CHECK(std::get<1>(t) == 8);
                CHECK(std::get<2>(t).x == 7);
            }

            {
                const json j = 7;
                CHECK_THROWS_AS((j.get<std::tuple<NonDefaultConstructible>>()), json::type_error);
            }
        }
    }

    SECTION("issue #4530 - Serialization of empty tuple")
    {
        const auto source_tuple = std::tuple<>();
        const nlohmann::json j = source_tuple;

        CHECK(j.get<decltype(source_tuple)>() == source_tuple);
        CHECK("[]" == j.dump());
    }

    SECTION("issue #2865 - ASAN detects memory leaks")
    {
        // the code below is expected to not leak memory
        {
            nlohmann::json o;
            const std::string s = "bar";

            nlohmann::to_json(o["foo"], s);

            nlohmann::json p = o;

            // call to_json with a non-null JSON value
            nlohmann::to_json(p["foo"], s);
        }

        {
            nlohmann::json o;
            const std::string s = "bar";

            nlohmann::to_json(o["foo"], s);

            // call to_json with a non-null JSON value
            nlohmann::to_json(o["foo"], s);
        }
    }

    SECTION("issue #2824 - encoding of json::exception::what()")
    {
        json j;
        sax_no_exception sax(j);

        CHECK(!json::sax_parse("xyz", &sax));
        CHECK(*sax_no_exception::error_string == "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'");
        delete sax_no_exception::error_string;  // NOLINT(cppcoreguidelines-owning-memory)
    }

    SECTION("issue #2825 - Properly constrain the basic_json conversion operator")
    {
        static_assert(std::is_copy_assignable<nlohmann::ordered_json>::value, "ordered_json must be copy assignable");
    }

    SECTION("issue #2958 - Inserting in unordered json using a pointer retains the leading slash")
    {
        const std::string p = "/root";

        json test1;
        test1[json::json_pointer(p)] = json::object();
        CHECK(test1.dump() == "{\"root\":{}}");

        ordered_json test2;
        test2[ordered_json::json_pointer(p)] = json::object();
        CHECK(test2.dump() == "{\"root\":{}}");

        // json::json_pointer and ordered_json::json_pointer are the same type; behave as above
        ordered_json test3;
        test3[json::json_pointer(p)] = json::object();
        CHECK(std::is_same<json::json_pointer::string_t, ordered_json::json_pointer::string_t>::value);
        CHECK(test3.dump() == "{\"root\":{}}");
    }

    SECTION("issue #2982 - to_{binary format} does not provide a mechanism for specifying a custom allocator for the returned type")
    {
        std::vector<std::uint8_t, my_allocator<std::uint8_t>> my_vector;
        const json j = {1, 2, 3, 4};
        json::to_cbor(j, my_vector);
        json k = json::from_cbor(my_vector);
        CHECK(j == k);
    }

#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
    // JSON_HAS_CPP_17 (do not remove; see note at top of file)
    SECTION("issue #3070 - Version 3.10.3 breaks backward-compatibility with 3.10.2 ")
    {
        nlohmann::detail::std_fs::path text_path("/tmp/text.txt");
        const json j(text_path);

        const auto j_path = j.get<nlohmann::detail::std_fs::path>();
        CHECK(j_path == text_path);

#if DOCTEST_CLANG || DOCTEST_GCC >= DOCTEST_COMPILER(8, 4, 0)
        // only known to work on Clang and GCC >=8.4
        CHECK_THROWS_WITH_AS(nlohmann::detail::std_fs::path(json(1)), "[json.exception.type_error.302] type must be string, but is number", json::type_error);
#endif
    }
#endif

    SECTION("issue #3077 - explicit constructor with default does not compile")
    {
        json j;
        j[0]["value"] = true;
        std::vector<FooBar> foo;
        j.get_to(foo);
    }

    SECTION("issue #3108 - ordered_json doesn't support range based erase")
    {
        ordered_json j = {1, 2, 2, 4};

        auto last = std::unique(j.begin(), j.end());
        j.erase(last, j.end());

        CHECK(j.dump() == "[1,2,4]");

        j.erase(std::remove_if(j.begin(), j.end(), [](const ordered_json & val)
        {
            return val == 2;
        }), j.end());

        CHECK(j.dump() == "[1,4]");
    }

    SECTION("issue #3343 - json and ordered_json are not interchangeable")
    {
        json::object_t jobj({ { "product", "one" } });
        ordered_json::object_t ojobj({{"product", "one"}});

        auto jit = jobj.begin();
        auto ojit = ojobj.begin();

        CHECK(jit->first == ojit->first);
        CHECK(jit->second.get<std::string>() == ojit->second.get<std::string>());
    }

    SECTION("issue #3171 - if class is_constructible from std::string wrong from_json overload is being selected, compilation failed")
    {
        const json j{{ "str", "value"}};

        // failed with: error: no match for ‘operator=’ (operand types are ‘for_3171_derived’ and ‘const nlohmann::basic_json<>::string_t’
        //                                               {aka ‘const std::__cxx11::basic_string<char>’})
        //                  s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
        auto td = j.get<for_3171_derived>();

        CHECK(td.str == "value");
    }

#ifdef JSON_HAS_CPP_20
    SECTION("issue #3312 - Parse to custom class from unordered_json breaks on G++11.2.0 with C++20")
    {
        // see test for #3171
        const ordered_json j = {{"name", "class"}};
        for_3312 obj{};

        j.get_to(obj);

        CHECK(obj.name == "class");
    }
#endif

#if defined(JSON_HAS_CPP_17) && JSON_USE_IMPLICIT_CONVERSIONS
    SECTION("issue #3428 - Error occurred when converting nlohmann::json to std::any")
    {
        const json j;
        const std::any a1 = j;
        std::any&& a2 = j;

        CHECK(a1.type() == typeid(j));
        CHECK(a2.type() == typeid(j));
    }
#endif

    SECTION("issue #3204 - ambiguous regression")
    {
        const for_3204_bar bar_from_foo([](for_3204_foo) noexcept {}); // NOLINT(performance-unnecessary-value-param)
        const for_3204_bar bar_from_json([](json) noexcept {}); // NOLINT(performance-unnecessary-value-param)

        CHECK(bar_from_foo.constructed_from == for_3204_bar::constructed_from_foo);
        CHECK(bar_from_json.constructed_from == for_3204_bar::constructed_from_json);
    }

    SECTION("issue #3333 - Ambiguous conversion from nlohmann::basic_json<> to custom class")
    {
        const json j
        {
            {"x", 1},
            {"y", 2}
        };
        const for_3333 p = j;

        CHECK(p.x == 1);
        CHECK(p.y == 2);
    }

    SECTION("issue #3810 - ordered_json doesn't support construction from C array of custom type")
    {
        Example_3810 states[45]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)

        // fix "not used" warning
        states[0].bla = 1;

        const auto* const expected = R"([{"bla":1},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0},{"bla":0}])";

        // This works:
        nlohmann::json j;
        j["test"] = states;
        CHECK(j["test"].dump() == expected);

        // This doesn't compile:
        nlohmann::ordered_json oj;
        oj["test"] = states;
        CHECK(oj["test"].dump() == expected);
    }

#ifdef JSON_HAS_CPP_17
    SECTION("issue #4740 - build issue with std::optional")
    {
        const auto t1 = Example_4740();
        const auto j1 = nlohmann::json(t1);
        CHECK(j1.dump() == "{\"host\":null,\"port\":null}");
        const auto t2 = j1.get<Example_4740>();
        CHECK(!t2.host.has_value());
        CHECK(!t2.port.has_value());

        // improve coverage
        auto t3 = Example_4740();
        t3.port = 80;
        t3.host = "example.com";
        const auto j2 = nlohmann::json(t3);
        CHECK(j2.dump() == "{\"host\":\"example.com\",\"port\":80}");
        const auto t4 = j2.get<Example_4740>();
        CHECK(t4.host.has_value());
        CHECK(t4.port.has_value());
    }
#endif

#if !defined(_MSVC_LANG)
    // MSVC returns garbage on invalid enum values, so this test is excluded
    // there.
    SECTION("issue #4762 - json exception 302 with unhelpful explanation : type must be number, but is number")
    {
        // In #4762, the main issue was that a json object with an invalid type
        // returned "number" as type_name(), because this was the default case.
        // This test makes sure we now return "invalid" instead.
        json j;
        j.m_data.m_type = static_cast<json::value_t>(100); // NOLINT(clang-analyzer-optin.core.EnumCastOutOfRange)
        CHECK(j.type_name() == "invalid");
    }
#endif

#ifdef JSON_HAS_CPP_17
    SECTION("issue #4804: from_cbor incompatible with std::vector<std::byte> as binary_t")
    {
        const std::vector<std::uint8_t> data = {0x80};
        const auto decoded = json_4804::from_cbor(data);
        CHECK((decoded == json_4804::array()));
    }

    SECTION("discussion #4209 - custom BinaryType direct assignment and round-tripping")
    {
        // Test that assigning a custom BinaryType directly creates a binary value, not an array
        const std::vector<std::byte> original{std::byte{1}, std::byte{2}, std::byte{3}};
        const json_4804 j = original;
        CHECK(j.is_binary());
        CHECK(!j.is_array());

        // Test round-tripping: extracting the binary value back as the custom container type
        const auto extracted = j.get<std::vector<std::byte>>();
        CHECK(extracted == original);

        // Test that the default json alias behavior is unchanged: std::vector<uint8_t> -> array
        const json default_json = std::vector<std::uint8_t> {1, 2, 3};
        CHECK(default_json.is_array());
        CHECK(!default_json.is_binary());
    }

    SECTION("discussion #4209 - custom BinaryType extraction from parsed array")
    {
        // Test that extracting a custom BinaryType from a parsed JSON array still works
        // (not just from a binary-typed node)
        const auto j = json_4804::parse("[1,2,3]");
        CHECK(j.is_array());
        CHECK(!j.is_binary());

        // Extracting as custom BinaryType should work from arrays
        const auto extracted = j.get<std::vector<std::byte>>();
        CHECK(extracted.size() == 3);
        CHECK(extracted[0] == std::byte{1});
        CHECK(extracted[1] == std::byte{2});
        CHECK(extracted[2] == std::byte{3});
    }

    SECTION("issue #5046 - implicit conversion of return json to std::optional no longer implicit")
    {
        const json jval{};
        auto GetValue = [](const json & valRoot) -> std::optional<json>
        {
            if (valRoot.contains("default"))
            {
                return valRoot.at("default");
            }
            return std::nullopt;
        };
        auto result = GetValue(jval);
        CHECK(!result.has_value());
    }
#endif

#if JSON_HAS_RANGES == 1
    SECTION("issue #4440 - assert when using std::views::filter and GCC 10")
    {
        auto noOpFilter = std::views::filter([](auto&&) noexcept
        {
            return true;
        });
        json j = {1, 2, 3};
        auto filtered = j | noOpFilter;
        CHECK(*filtered.begin() == 1);
    }
#endif

#if JSON_HAS_RANGES && !defined(__MINGW32__)
    SECTION("issue #4916 - constructing array from C++20 ranges view does not work")
    {
        std::vector<int> nums{1, 2, 37, 42, 21};
        auto filteredNums = nums | std::views::filter([](int i)
        {
            return i > 10;
        });
        json const j(filteredNums);
        CHECK(j.type() == json::value_t::array);
        CHECK(j == json({37, 42, 21}));
    }
#endif

    // owning_view is not available in libstdc++ < 12
#if JSON_HAS_RANGES && !defined(__MINGW32__) && !(defined(__GLIBCXX__) && _GLIBCXX_RELEASE < 12)
    SECTION("issue #4916 - constructing array from prvalue C++20 ranges view (owning_view)")
    {
        json const j(std::vector<int> {1, 2, 37, 42, 21} | std::views::filter([](int i)
        {
            return i > 10;
        }));
        CHECK(j.type() == json::value_t::array);
        CHECK(j == json({37, 42, 21}));
    }
#endif

#if JSON_HAS_RANGES && !defined(__MINGW32__)
    SECTION("issue #4916 - constructing array from C++20 transform view (prvalue elements)")
    {
        std::vector<int> nums{1, 2, 3};
        auto t = nums | std::views::transform([](int i) noexcept
        {
            return i * 2;
        });
        json const j(t);
        CHECK(j.type() == json::value_t::array);
        CHECK(j == json({2, 4, 6}));
    }
#endif
}

TEST_CASE_TEMPLATE("issue #4798 - nlohmann::json::to_msgpack() encode float NaN as double", T, double, float) // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization)
{
    // With issue #4798, we encode NaN, infinity, and -infinity as float instead
    // of double to allow for smaller encodings.
    const json jx = std::numeric_limits<T>::quiet_NaN();
    const json jy = std::numeric_limits<T>::infinity();
    const json jz = -std::numeric_limits<T>::infinity();

    /////////////////////////////////////////////////////////////////////////
    // MessagePack
    /////////////////////////////////////////////////////////////////////////

    // expected MessagePack values
    const std::vector<std::uint8_t> msgpack_x = {{0xCA, 0x7F, 0xC0, 0x00, 0x00}};
    const std::vector<std::uint8_t> msgpack_y = {{0xCA, 0x7F, 0x80, 0x00, 0x00}};
    const std::vector<std::uint8_t> msgpack_z = {{0xCA, 0xFF, 0x80, 0x00, 0x00}};

    CHECK(json::to_msgpack(jx) == msgpack_x);
    CHECK(json::to_msgpack(jy) == msgpack_y);
    CHECK(json::to_msgpack(jz) == msgpack_z);

    CHECK(std::isnan(json::from_msgpack(msgpack_x).get<T>()));
    CHECK(json::from_msgpack(msgpack_y).get<T>() == std::numeric_limits<T>::infinity());
    CHECK(json::from_msgpack(msgpack_z).get<T>() == -std::numeric_limits<T>::infinity());

    // Make sure the other MessagePakc encodings for NaN, infinity, and
    // -infinity are still supported.
    const std::vector<std::uint8_t> msgpack_x_2 = {{0xCB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
    const std::vector<std::uint8_t> msgpack_y_2 = {{0xCB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
    const std::vector<std::uint8_t> msgpack_z_2 = {{0xCB, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
    CHECK(std::isnan(json::from_msgpack(msgpack_x_2).get<T>()));
    CHECK(json::from_msgpack(msgpack_y_2).get<T>() == std::numeric_limits<T>::infinity());
    CHECK(json::from_msgpack(msgpack_z_2).get<T>() == -std::numeric_limits<T>::infinity());

    /////////////////////////////////////////////////////////////////////////
    // CBOR
    /////////////////////////////////////////////////////////////////////////

    // expected CBOR values
    const std::vector<std::uint8_t> cbor_x = {{0xF9, 0x7E, 0x00}};
    const std::vector<std::uint8_t> cbor_y = {{0xF9, 0x7C, 0x00}};
    const std::vector<std::uint8_t> cbor_z = {{0xF9, 0xfC, 0x00}};

    CHECK(json::to_cbor(jx) == cbor_x);
    CHECK(json::to_cbor(jy) == cbor_y);
    CHECK(json::to_cbor(jz) == cbor_z);

    CHECK(std::isnan(json::from_cbor(cbor_x).get<T>()));
    CHECK(json::from_cbor(cbor_y).get<T>() == std::numeric_limits<T>::infinity());
    CHECK(json::from_cbor(cbor_z).get<T>() == -std::numeric_limits<T>::infinity());

    // Make sure the other CBOR encodings for NaN, infinity, and -infinity are
    // still supported.
    const std::vector<std::uint8_t> cbor_x_2 = {{0xFA, 0x7F, 0xC0, 0x00, 0x00}};
    const std::vector<std::uint8_t> cbor_y_2 = {{0xFA, 0x7F, 0x80, 0x00, 0x00}};
    const std::vector<std::uint8_t> cbor_z_2 = {{0xFA, 0xFF, 0x80, 0x00, 0x00}};
    const std::vector<std::uint8_t> cbor_x_3 = {{0xFB, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
    const std::vector<std::uint8_t> cbor_y_3 = {{0xFB, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
    const std::vector<std::uint8_t> cbor_z_3 = {{0xFB, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
    CHECK(std::isnan(json::from_cbor(cbor_x_2).get<T>()));
    CHECK(json::from_cbor(cbor_y_2).get<T>() == std::numeric_limits<T>::infinity());
    CHECK(json::from_cbor(cbor_z_2).get<T>() == -std::numeric_limits<T>::infinity());
    CHECK(std::isnan(json::from_cbor(cbor_x_3).get<T>()));
    CHECK(json::from_cbor(cbor_y_3).get<T>() == std::numeric_limits<T>::infinity());
    CHECK(json::from_cbor(cbor_z_3).get<T>() == -std::numeric_limits<T>::infinity());
}

TEST_CASE("regression test #5074 - portable workaround for single-element brace init")
{
    json const j_obj = {{"key", "value"}};

    json const j = json::array({j_obj});
    CHECK(j.is_array());
    CHECK(j.size() == 1);
    CHECK(j[0] == j_obj);
}

#if defined(JSON_BRACE_INIT_COPY_SEMANTICS) && (JSON_BRACE_INIT_COPY_SEMANTICS == 1)
TEST_CASE("regression test #5074 - single-element brace init with JSON_BRACE_INIT_COPY_SEMANTICS")
{
    // with JSON_BRACE_INIT_COPY_SEMANTICS: single-element brace init copies/moves
    json const j_obj = {{"key", "value"}, {"num", 42}};
    json const j_arr = {1, 2, 3};

    // object: brace init copies instead of wrapping
    json const j1{j_obj};
    CHECK(j1.is_object());
    CHECK(j1 == j_obj);

    // array: brace init copies instead of wrapping
    json const j2{j_arr};
    CHECK(j2.is_array());
    CHECK(j2.size() == 3);
    CHECK(j2 == j_arr);

    // primitives still work as initializer lists
    json const j3{true};
    CHECK(j3.is_boolean());

    json const j4{42};
    CHECK(j4.is_number_integer());
}
#endif

struct Example_5122
{
    float b = 2;
    nlohmann::ordered_map<std::string, std::string> c{}; // NOLINT(readability-redundant-member-init): needed for GCC -Weffc++
    int a = 1;
    NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Example_5122, b, c, a)
};

TEST_CASE("regression test #5122 - from_json into types holding nlohmann::ordered_map")
{
    Example_5122 src;
    src.c.emplace("first", "1");
    src.c.emplace("second", "2");

    ordered_json const j = src;
    Example_5122 const dst = j.get<Example_5122>();

    CHECK(dst.b == src.b);
    CHECK(dst.a == src.a);
    REQUIRE(dst.c.size() == src.c.size());
    auto src_it = src.c.begin();
    auto dst_it = dst.c.begin();
    for (; src_it != src.c.end(); ++src_it, ++dst_it)
    {
        CHECK(dst_it->first == src_it->first);
        CHECK(dst_it->second == src_it->second);
    }
}

// -Wself-assign-overloaded was introduced in Clang 7. Gate the pragma on
// __has_warning so older Clang versions do not error with "unknown warning
// group". The __has_warning check has to stay inside the __clang__ branch
// because GCC does not provide it and would tokenize-error on the argument.
#if defined(__clang__) && defined(__has_warning)
    #if __has_warning("-Wself-assign-overloaded")
        DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
        DOCTEST_CLANG_SUPPRESS_WARNING("-Wself-assign-overloaded")
    #endif
#endif

TEST_CASE("regression test #5122 - nlohmann::ordered_map copy-assignment is self-assignment safe")
{
    nlohmann::ordered_map<std::string, std::string> m;
    m.emplace("first", "1");
    m.emplace("second", "2");

    // Insertion order is preserved by ordered_map, so we can check it directly.
    m = m;

    REQUIRE(m.size() == 2);
    auto it = m.begin();
    CHECK(it->first == "first");
    CHECK(it->second == "1");
    ++it;
    CHECK(it->first == "second");
    CHECK(it->second == "2");
}

#if defined(__clang__) && defined(__has_warning)
    #if __has_warning("-Wself-assign-overloaded")
        DOCTEST_CLANG_SUPPRESS_WARNING_POP
    #endif
#endif

TEST_CASE("regression test #5122 - nlohmann::ordered_map move-assignment transfers contents")
{
    nlohmann::ordered_map<std::string, std::string> src;
    src.emplace("first", "1");
    src.emplace("second", "2");

    nlohmann::ordered_map<std::string, std::string> dst;
    dst.emplace("stale", "x");
    dst = std::move(src);

    REQUIRE(dst.size() == 2);
    auto it = dst.begin();
    CHECK(it->first == "first");
    CHECK(it->second == "1");
    ++it;
    CHECK(it->first == "second");
    CHECK(it->second == "2");

    // Re-assigning into the moved-from object must leave it in a usable state.
    src = nlohmann::ordered_map<std::string, std::string> {};
    src.emplace("after-move", "3");
    REQUIRE(src.size() == 1);
    CHECK(src.begin()->first == "after-move");
}

// Stand-in for a third-party library (e.g., Eigen as of 3.4, which added
// STL-compatible begin()/end() to its vector types), living in its own
// namespace with its own to_json overload for its vector type.
namespace issue_4320_eigen
{
// "array-compatible" from the library's point of view (it has begin()/end()),
// but for which this (fake) third-party namespace provides its own to_json.
struct vector3
{
    double v[3]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-use-default-member-init,modernize-use-default-member-init)
    vector3(double x, double y, double z) : v{x, y, z} {} // NOLINT(hicpp-member-init,cppcoreguidelines-pro-type-member-init)
    double x() const
    {
        return v[0];
    }
    double y() const
    {
        return v[1];
    }
    double z() const
    {
        return v[2];
    }
    double* begin()
    {
        return v;
    }
    double* end()
    {
        return v + 3;
    }
    const double* begin() const
    {
        return v;
    }
    const double* end() const
    {
        return v + 3;
    }
};

inline void to_json(json& j, const vector3& v) // NOLINT(misc-use-internal-linkage)
{
    j = {{"x", v.x()}, {"y", v.y()}, {"z", v.z()}};
}
} // namespace issue_4320_eigen

// The user's own namespace, using the (fake) Eigen type as an implementation
// detail behind a payload type that has nothing to do with vectors/arrays.
namespace issue_4320
{
// Publicly derives from issue_4320_eigen::vector3 but does *not* define its
// own to_json - it is only ever used as a temporary to reach the base
// class's to_json via ADL.
struct vector3_wrapper : issue_4320_eigen::vector3
{
    using issue_4320_eigen::vector3::vector3;
};

struct payload
{
    double x, y, z;
};

inline vector3_wrapper to_eigen(const payload& p) // NOLINT(misc-use-internal-linkage)
{
    return {p.x, p.y, p.z};
}

inline void to_json(json& j, const payload& p) // NOLINT(misc-use-internal-linkage)
{
    // Unqualified call, passing a *derived* vector3_wrapper: relies on ADL
    // finding issue_4320_eigen::to_json(json&, const vector3&) through the
    // vector3 base class, via a derived-to-base conversion. Must NOT resolve
    // to the library's own generic array-compatible to_json (an exact-match
    // template for vector3_wrapper, since it also has begin()/end()), which
    // would serialize this as [x, y, z] instead of {"x":x, "y":y, "z":z}.
    to_json(j, to_eigen(p));
}
} // namespace issue_4320

TEST_CASE("issue #4320 - custom base class must not leak nlohmann::detail into ADL")
{
    // Before the fix, basic_json unconditionally derived from a type living in
    // nlohmann::detail (json_default_base), which made nlohmann::detail an
    // associated namespace of every basic_json for ADL purposes. That leaked
    // the library's internal generic-array to_json overload into unqualified
    // to_json() calls made from user code, silently bypassing user-defined
    // to_json overloads reached via a derived-to-base conversion.
    const issue_4320::payload p{1.0, 2.0, 3.0};

    json j;
    to_json(j, p);
    CHECK(j == json({{"x", 1.0}, {"y", 2.0}, {"z", 3.0}}));
}

TEST_CASE("issue #5338 - truncated CBOR tagged binary subtype is rejected")
{
    const std::vector<std::vector<std::uint8_t>> truncated_tags =
    {
        {0xD8},
        {0xD9, 0x00},
        {0xDA, 0x00, 0x00, 0x00},
        {0xDB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
    };

    for (const auto& data : truncated_tags)
    {
        CAPTURE(data);
        for (const auto tag_handler :
                {
                    json::cbor_tag_handler_t::ignore, json::cbor_tag_handler_t::store
                })
        {
            CAPTURE(tag_handler);
            const auto result = json::from_cbor(data, true, false, tag_handler);
            CHECK(result.is_discarded());
        }
    }
}

DOCTEST_CLANG_SUPPRESS_WARNING_POP


//     __ _____ _____ _____
//  __|  |   __|     |   | |  JSON for Modern C++
// |  |  |__   |  |  | | | |  version 3.12.0
// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT

#pragma once

#include <array> // array
#include <cstddef> // size_t
#include <cstdint> // uint8_t
#include <string> // string

#include <nlohmann/detail/macro_scope.hpp>
#if JSON_HAS_THREE_WAY_COMPARISON
    #include <compare> // partial_ordering
#endif

NLOHMANN_JSON_NAMESPACE_BEGIN
namespace detail
{

///////////////////////////
// JSON type enumeration //
///////////////////////////

/*!
@brief the JSON type enumeration

This enumeration collects the different JSON types. It is internally used to
distinguish the stored values, and the functions @ref basic_json::is_null(),
@ref basic_json::is_object(), @ref basic_json::is_array(),
@ref basic_json::is_string(), @ref basic_json::is_boolean(),
@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
@ref basic_json::is_structured() rely on it.

@note There are three enumeration entries (number_integer, number_unsigned, and
number_float), because the library distinguishes these three types for numbers:
@ref basic_json::number_unsigned_t is used for unsigned integers,
@ref basic_json::number_integer_t is used for signed integers, and
@ref basic_json::number_float_t is used for floating-point numbers or to
approximate integers which do not fit in the limits of their respective type.

@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
value with the default value for a given type

@since version 1.0.0
*/
enum class value_t : std::uint8_t
{
    null,             ///< null value
    object,           ///< object (unordered set of name/value pairs)
    array,            ///< array (ordered collection of values)
    string,           ///< string value
    boolean,          ///< boolean value
    number_integer,   ///< number value (signed integer)
    number_unsigned,  ///< number value (unsigned integer)
    number_float,     ///< number value (floating-point)
    binary,           ///< binary array (ordered collection of bytes)
    discarded         ///< discarded by the parser callback function
};

/*!
@brief comparison operator for JSON types

Returns an ordering that is similar to Python:
- order: null < boolean < number < object < array < string < binary
- furthermore, each type is not smaller than itself
- discarded values are not comparable
- binary is represented as a b"" string in python and directly comparable to a
  string; however, making a binary array directly comparable with a string would
  be surprising behavior in a JSON file.

@since version 1.0.0
*/
#if JSON_HAS_THREE_WAY_COMPARISON
    inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
#else
    inline bool operator<(const value_t lhs, const value_t rhs) noexcept
#endif
{
    static constexpr std::array<std::uint8_t, 9> order = {{
            0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
            1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
            6 /* binary */
        }
    };

    const auto l_index = static_cast<std::size_t>(lhs);
    const auto r_index = static_cast<std::size_t>(rhs);
#if JSON_HAS_THREE_WAY_COMPARISON
    if (l_index < order.size() && r_index < order.size())
    {
        return order[l_index] <=> order[r_index]; // *NOPAD*
    }
    return std::partial_ordering::unordered;
#else
    return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
#endif
}

// GCC selects the built-in operator< over an operator rewritten from
// a user-defined spaceship operator
// Clang, MSVC, and ICC select the rewritten candidate
// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
{
    return std::is_lt(lhs <=> rhs); // *NOPAD*
}
#endif

}  // namespace detail
NLOHMANN_JSON_NAMESPACE_END


# <small>nlohmann::</small>byte_container_with_subtype

```cpp
template<typename BinaryType>
class byte_container_with_subtype : public BinaryType;
```

This type extends the template parameter `BinaryType` provided to [`basic_json`](../basic_json/index.md) with a subtype
used by BSON and MessagePack. This type exists so that the user does not have to specify a type themselves with a
specific naming scheme in order to override the binary type.

## Template parameters

`BinaryType`
:   container to store bytes (`#!cpp std::vector<std::uint8_t>` by default)

## Member types

- **container_type** - the type of the underlying container (`BinaryType`)
- **subtype_type** - the type of the subtype (`#!cpp std::uint64_t`)

## Member functions

- [(constructor)](byte_container_with_subtype.md)
- **operator==** - comparison: equal
- **operator!=** - comparison: not equal
- [**set_subtype**](set_subtype.md) - sets the binary subtype
- [**subtype**](subtype.md) - return the binary subtype
- [**has_subtype**](has_subtype.md) - return whether the value has a subtype
- [**clear_subtype**](clear_subtype.md) - clears the binary subtype

## Version history

- Added in version 3.8.0.
- Changed the type of subtypes to `#!cpp std::uint64_t` in 3.10.0.


//===- FuzzerSHA1.h - Internal header for the SHA1 utils --------*- C++ -* ===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// SHA1 utils.
//===----------------------------------------------------------------------===//

#ifndef LLVM_FUZZER_SHA1_H
#define LLVM_FUZZER_SHA1_H

#include "FuzzerDefs.h"
#include <cstddef>
#include <stdint.h>

namespace fuzzer {

// Private copy of SHA1 implementation.
static const int kSHA1NumBytes = 20;

// Computes SHA1 hash of 'Len' bytes in 'Data', writes kSHA1NumBytes to 'Out'.
void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out);

std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]);

std::string Hash(const Unit &U);

}  // namespace fuzzer

#endif  // LLVM_FUZZER_SHA1_H