#![deny(trivial_numeric_casts)]
#![allow(
    clippy::derive_partial_eq_without_eq,
    clippy::enum_variant_names,
    clippy::redundant_field_names,
    clippy::too_many_lines
)]

use serde_derive::{Deserialize, Serialize};
use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token};

#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "t", content = "c")]
enum AdjacentlyTagged<T> {
    Unit,
    Newtype(T),
    Tuple(u8, u8),
    Struct { f: u8 },
}

mod unit {
    use super::*;

    #[test]
    fn map_str_tag_only() {
        // Map: tag only
        assert_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 1,
                },
                Token::Str("t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Unit",
                },
                Token::StructEnd,
            ],
        );

        // Map: tag only and incorrect hint for number of elements
        assert_de_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 2,
                },
                Token::Str("t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Unit",
                },
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn map_int_tag_only() {
        // Map: tag (as number) only
        assert_de_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 1,
                },
                Token::U16(0),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Unit",
                },
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn map_bytes_tag_only() {
        // Map: tag only
        assert_de_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 1,
                },
                Token::Bytes(b"t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Unit",
                },
                Token::StructEnd,
            ],
        );

        // Map: tag only
        assert_de_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 1,
                },
                Token::BorrowedBytes(b"t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Unit",
                },
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn map_str_tag_content() {
        // Map: tag + content
        assert_de_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 2,
                },
                Token::Str("t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Unit",
                },
                Token::Str("c"),
                Token::Unit,
                Token::StructEnd,
            ],
        );
        // Map: content + tag
        assert_de_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 2,
                },
                Token::Str("c"),
                Token::Unit,
                Token::Str("t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Unit",
                },
                Token::StructEnd,
            ],
        );

        // Map: tag + content + excess fields (f, g, h)
        assert_de_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 2,
                },
                Token::Str("f"),
                Token::Unit,
                Token::Str("t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Unit",
                },
                Token::Str("g"),
                Token::Unit,
                Token::Str("c"),
                Token::Unit,
                Token::Str("h"),
                Token::Unit,
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn map_int_tag_content() {
        // Map: tag (as number) + content (as number)
        assert_de_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 2,
                },
                Token::U8(0),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Unit",
                },
                Token::U8(1),
                Token::Unit,
                Token::StructEnd,
            ],
        );

        // Map: content (as number) + tag (as number)
        assert_de_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 2,
                },
                Token::U64(1),
                Token::Unit,
                Token::U64(0),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Unit",
                },
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn map_bytes_tag_content() {
        // Map: tag + content
        assert_de_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 2,
                },
                Token::BorrowedBytes(b"t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Unit",
                },
                Token::BorrowedBytes(b"c"),
                Token::Unit,
                Token::StructEnd,
            ],
        );

        // Map: content + tag
        assert_de_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 2,
                },
                Token::Bytes(b"c"),
                Token::Unit,
                Token::Bytes(b"t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Unit",
                },
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn seq_tag_content() {
        // Seq: tag and content
        assert_de_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Seq { len: Some(2) },
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Unit",
                },
                Token::Unit,
                Token::SeqEnd,
            ],
        );

        // Seq: tag (as string) and content
        assert_de_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Seq { len: None },
                Token::Str("Unit"), // tag
                Token::Unit,        // content
                Token::SeqEnd,
            ],
        );

        // Seq: tag (as borrowed string) and content
        assert_de_tokens(
            &AdjacentlyTagged::Unit::<u8>,
            &[
                Token::Seq { len: None },
                Token::BorrowedStr("Unit"), // tag
                Token::Unit,                // content
                Token::SeqEnd,
            ],
        );
    }
}

mod newtype {
    use super::*;

    #[test]
    fn map_tag_only() {
        // optional newtype with no content field
        assert_de_tokens(
            &AdjacentlyTagged::Newtype::<Option<u8>>(None),
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 1,
                },
                Token::Str("t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Newtype",
                },
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn map_tag_content() {
        let value = AdjacentlyTagged::Newtype::<u8>(1);

        // Map: tag + content
        assert_tokens(
            &value,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 2,
                },
                Token::Str("t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Newtype",
                },
                Token::Str("c"),
                Token::U8(1),
                Token::StructEnd,
            ],
        );

        // Map: content + tag
        assert_de_tokens(
            &value,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 2,
                },
                Token::Str("c"),
                Token::U8(1),
                Token::Str("t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Newtype",
                },
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn seq() {
        let value = AdjacentlyTagged::Newtype::<u8>(1);

        // Seq: tag and content
        assert_de_tokens(
            &value,
            &[
                Token::Seq { len: Some(2) },
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Newtype",
                },
                Token::U8(1),
                Token::SeqEnd,
            ],
        );

        // Seq: tag (as string) and content
        assert_de_tokens(
            &value,
            &[
                Token::Seq { len: None },
                Token::Str("Newtype"), // tag
                Token::U8(1),          // content
                Token::SeqEnd,
            ],
        );

        // Seq: tag (as borrowed string) and content
        assert_de_tokens(
            &value,
            &[
                Token::Seq { len: None },
                Token::BorrowedStr("Newtype"), // tag
                Token::U8(1),                  // content
                Token::SeqEnd,
            ],
        );
    }
}

#[test]
fn newtype_with_newtype() {
    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    struct NewtypeStruct(u32);

    assert_de_tokens(
        &AdjacentlyTagged::Newtype(NewtypeStruct(5)),
        &[
            Token::Struct {
                name: "AdjacentlyTagged",
                len: 2,
            },
            Token::Str("c"),
            Token::NewtypeStruct {
                name: "NewtypeStruct",
            },
            Token::U32(5),
            Token::Str("t"),
            Token::UnitVariant {
                name: "AdjacentlyTagged",
                variant: "Newtype",
            },
            Token::StructEnd,
        ],
    );
}

mod tuple {
    use super::*;

    #[test]
    fn map() {
        let value = AdjacentlyTagged::Tuple::<u8>(1, 1);

        // Map: tag + content
        assert_tokens(
            &value,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 2,
                },
                Token::Str("t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Tuple",
                },
                Token::Str("c"),
                Token::Tuple { len: 2 },
                Token::U8(1),
                Token::U8(1),
                Token::TupleEnd,
                Token::StructEnd,
            ],
        );

        // Map: content + tag
        assert_de_tokens(
            &value,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 2,
                },
                Token::Str("c"),
                Token::Tuple { len: 2 },
                Token::U8(1),
                Token::U8(1),
                Token::TupleEnd,
                Token::Str("t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Tuple",
                },
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn seq() {
        let value = AdjacentlyTagged::Tuple::<u8>(1, 1);

        // Seq: tag + content
        assert_de_tokens(
            &value,
            &[
                Token::Seq { len: Some(2) },
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Tuple",
                },
                Token::Tuple { len: 2 },
                Token::U8(1),
                Token::U8(1),
                Token::TupleEnd,
                Token::SeqEnd,
            ],
        );
    }
}

mod struct_ {
    use super::*;

    #[test]
    fn map() {
        let value = AdjacentlyTagged::Struct::<u8> { f: 1 };

        // Map: tag + content
        assert_tokens(
            &value,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 2,
                },
                Token::Str("t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Struct",
                },
                Token::Str("c"),
                Token::Struct {
                    name: "Struct",
                    len: 1,
                },
                Token::Str("f"),
                Token::U8(1),
                Token::StructEnd,
                Token::StructEnd,
            ],
        );

        // Map: content + tag
        assert_de_tokens(
            &value,
            &[
                Token::Struct {
                    name: "AdjacentlyTagged",
                    len: 2,
                },
                Token::Str("c"),
                Token::Struct {
                    name: "Struct",
                    len: 1,
                },
                Token::Str("f"),
                Token::U8(1),
                Token::StructEnd,
                Token::Str("t"),
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Struct",
                },
                Token::StructEnd,
            ],
        );
    }

    #[test]
    fn seq() {
        let value = AdjacentlyTagged::Struct::<u8> { f: 1 };

        // Seq: tag + content
        assert_de_tokens(
            &value,
            &[
                Token::Seq { len: Some(2) },
                Token::UnitVariant {
                    name: "AdjacentlyTagged",
                    variant: "Struct",
                },
                Token::Struct {
                    name: "Struct",
                    len: 1,
                },
                Token::Str("f"),
                Token::U8(1),
                Token::StructEnd,
                Token::SeqEnd,
            ],
        );
    }
}

#[test]
fn struct_with_flatten() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    #[serde(tag = "t", content = "c")]
    enum Data {
        A {
            a: i32,
            #[serde(flatten)]
            flat: Flat,
        },
    }

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Flat {
        b: i32,
    }

    let data = Data::A {
        a: 0,
        flat: Flat { b: 0 },
    };

    assert_tokens(
        &data,
        &[
            Token::Struct {
                name: "Data",
                len: 2,
            },
            Token::Str("t"),
            Token::UnitVariant {
                name: "Data",
                variant: "A",
            },
            Token::Str("c"),
            Token::Map { len: None },
            Token::Str("a"),
            Token::I32(0),
            Token::Str("b"),
            Token::I32(0),
            Token::MapEnd,
            Token::StructEnd,
        ],
    );
}

#[test]
fn expecting_message() {
    #[derive(Deserialize)]
    #[serde(tag = "tag", content = "content")]
    #[serde(expecting = "something strange...")]
    enum Enum {
        AdjacentlyTagged,
    }

    assert_de_tokens_error::<Enum>(
        &[Token::Str("AdjacentlyTagged")],
        r#"invalid type: string "AdjacentlyTagged", expected something strange..."#,
    );

    assert_de_tokens_error::<Enum>(
        &[Token::Map { len: None }, Token::Unit],
        r#"invalid type: unit value, expected "tag", "content", or other ignored fields"#,
    );

    // Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
    assert_de_tokens_error::<Enum>(
        &[Token::Map { len: None }, Token::Str("tag"), Token::Unit],
        "invalid type: unit value, expected variant of enum Enum",
    );
}

#[test]
fn partially_untagged() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    #[serde(tag = "t", content = "c")]
    enum Data {
        A(u32),
        B,
        #[serde(untagged)]
        Var(u32),
    }

    let data = Data::A(7);

    assert_de_tokens(
        &data,
        &[
            Token::Map { len: None },
            Token::Str("t"),
            Token::Str("A"),
            Token::Str("c"),
            Token::U32(7),
            Token::MapEnd,
        ],
    );

    let data = Data::Var(42);

    assert_de_tokens(&data, &[Token::U32(42)]);

    // TODO test error output
}

#[test]
fn deny_unknown_fields() {
    #[derive(Debug, PartialEq, Deserialize)]
    #[serde(tag = "t", content = "c", deny_unknown_fields)]
    enum AdjacentlyTagged {
        Unit,
    }

    assert_de_tokens(
        &AdjacentlyTagged::Unit,
        &[
            Token::Struct {
                name: "AdjacentlyTagged",
                len: 2,
            },
            Token::Str("t"),
            Token::UnitVariant {
                name: "AdjacentlyTagged",
                variant: "Unit",
            },
            Token::Str("c"),
            Token::Unit,
            Token::StructEnd,
        ],
    );

    assert_de_tokens_error::<AdjacentlyTagged>(
        &[
            Token::Struct {
                name: "AdjacentlyTagged",
                len: 2,
            },
            Token::Str("t"),
            Token::UnitVariant {
                name: "AdjacentlyTagged",
                variant: "Unit",
            },
            Token::Str("c"),
            Token::Unit,
            Token::Str("h"),
        ],
        r#"invalid value: string "h", expected "t" or "c""#,
    );

    assert_de_tokens_error::<AdjacentlyTagged>(
        &[
            Token::Struct {
                name: "AdjacentlyTagged",
                len: 2,
            },
            Token::Str("h"),
        ],
        r#"invalid value: string "h", expected "t" or "c""#,
    );

    assert_de_tokens_error::<AdjacentlyTagged>(
        &[
            Token::Struct {
                name: "AdjacentlyTagged",
                len: 2,
            },
            Token::Str("c"),
            Token::Unit,
            Token::Str("h"),
        ],
        r#"invalid value: string "h", expected "t" or "c""#,
    );

    assert_de_tokens_error::<AdjacentlyTagged>(
        &[
            Token::Struct {
                name: "AdjacentlyTagged",
                len: 2,
            },
            Token::U64(0), // tag field
            Token::UnitVariant {
                name: "AdjacentlyTagged",
                variant: "Unit",
            },
            Token::U64(3),
        ],
        r#"invalid value: integer `3`, expected "t" or "c""#,
    );

    assert_de_tokens_error::<AdjacentlyTagged>(
        &[
            Token::Struct {
                name: "AdjacentlyTagged",
                len: 2,
            },
            Token::Bytes(b"c"),
            Token::Unit,
            Token::Bytes(b"h"),
        ],
        r#"invalid value: byte array, expected "t" or "c""#,
    );
}


# Shared Plugins during Build

::: tip Feedback
Give us feedback at [Environment API feedback discussion](https://github.com/vitejs/vite/discussions/16358)
:::

See [Shared plugins during build](/guide/api-environment-plugins.md#shared-plugins-during-build).

Affected scope: `Vite Plugin Authors`

::: warning Future Default Change
`builder.sharedConfigBuild` was first introduced in `v6.0`. You can set it true to check how your plugins work with a shared config. We're looking for feedback about changing the default in a future major once the plugin ecosystem is ready.
:::

## Motivation

Align dev and build plugin pipelines.

## Migration Guide

To be able to share plugins across environments, plugin state must be keyed by the current environment. A plugin of the following form will count the number of transformed modules across all environments.

```js
function CountTransformedModulesPlugin() {
  let transformedModules
  return {
    name: 'count-transformed-modules',
    buildStart() {
      transformedModules = 0
    },
    transform(id) {
      transformedModules++
    },
    buildEnd() {
      console.log(transformedModules)
    },
  }
}
```

If we instead want to count the number of transformed modules for each environment, we need to keep a map:

```ts
function PerEnvironmentCountTransformedModulesPlugin() {
  const state = new Map<Environment, { count: number }>()
  return {
    name: 'count-transformed-modules',
    perEnvironmentStartEndDuringDev: true,
    buildStart() {
      state.set(this.environment, { count: 0 })
    },
    transform(id) {
      state.get(this.environment).count++
    },
    buildEnd() {
      console.log(this.environment.name, state.get(this.environment).count)
    },
  }
}
```

To simplify this pattern, Vite exports a `perEnvironmentState` helper:

```ts
function PerEnvironmentCountTransformedModulesPlugin() {
  const state = perEnvironmentState<{ count: number }>(() => ({ count: 0 }))
  return {
    name: 'count-transformed-modules',
    perEnvironmentStartEndDuringDev: true,
    buildStart() {
      state(this).count = 0
    },
    transform(id) {
      state(this).count++
    },
    buildEnd() {
      console.log(this.environment.name, state(this).count)
    },
  }
}
```


import { join } from 'node:path'
import { describe, expect, test } from 'vitest'
import { loadEnv } from '../env'

const dirname = import.meta.dirname

describe('loadEnv', () => {
  test('basic', () => {
    expect(loadEnv('development', join(dirname, './env')))
      .toMatchInlineSnapshot(`
        {
          "VITE_APP_BASE_ROUTE": "/",
          "VITE_APP_BASE_URL": "/",
          "VITE_ENV1": "ENV1",
          "VITE_ENV2": "ENV2",
          "VITE_ENV3": "ENV3",
        }
      `)
  })

  test('specific prefix', () => {
    expect(loadEnv('development', join(dirname, './env'), 'VVITE'))
      .toMatchInlineSnapshot(`
        {
          "VVITE_A": "A",
          "VVITE_B": "B",
        }
      `)
  })

  test('override', () => {
    expect(loadEnv('production', join(dirname, './env')))
      .toMatchInlineSnapshot(`
        {
          "VITE_APP_BASE_ROUTE": "/app/",
          "VITE_APP_BASE_URL": "/app/",
        }
      `)
  })

  test('override 2', () => {
    expect(loadEnv('development2', join(dirname, './env')))
      .toMatchInlineSnapshot(`
        {
          "VITE_APP_BASE_ROUTE": "source",
          "VITE_APP_BASE_URL": "source",
          "VITE_SOURCE": "source",
        }
      `)
  })

  test('VITE_USER_NODE_ENV', () => {
    loadEnv('development', join(dirname, './env'))
    expect(process.env.VITE_USER_NODE_ENV).toEqual(undefined)
  })

  test('VITE_USER_NODE_ENV for dev behaviour in build', () => {
    const _nodeEnv = process.env.NODE_ENV
    process.env.NODE_ENV = 'production'
    loadEnv('testing', join(dirname, './env'))
    expect(process.env.VITE_USER_NODE_ENV).toEqual('development')
    process.env.NODE_ENV = _nodeEnv
  })

  test('Already exists VITE_USER_NODE_ENV', () => {
    process.env.VITE_USER_NODE_ENV = 'test'
    loadEnv('development', join(dirname, './env'))
    expect(process.env.VITE_USER_NODE_ENV).toEqual('test')
  })

  test('prioritize existing process.env', () => {
    process.env.VITE_ENV_TEST_ENV = 'EXIST'
    expect(loadEnv('existing', join(dirname, './env'))).toMatchInlineSnapshot(`
        {
          "VITE_APP_BASE_ROUTE": "/",
          "VITE_APP_BASE_URL": "/",
          "VITE_ENV_TEST_ENV": "EXIST",
          "VITE_USER_NODE_ENV": "test",
        }
      `)
  })
})


import { defineConfig } from 'vite'
import baseConfig from './vite.config.js'

const dynamicBaseAssetsCode = `
globalThis.__toAssetUrl = url => '/' + url
globalThis.__publicBase = '/'
`

export default defineConfig({
  ...baseConfig,
  base: './', // overwrite the original base: '/foo/'
  build: {
    ...baseConfig.build,
    outDir: 'dist/runtime-base',
    watch: null,
    minify: false,
    assetsInlineLimit: 0,
    rolldownOptions: {
      output: {
        entryFileNames: 'entries/[name].js',
        chunkFileNames: 'chunks/[name]-[hash].js',
        assetFileNames: 'other-assets/[name]-[hash][extname]',
      },
    },
  },
  plugins: [
    {
      name: 'dynamic-base-assets-globals',
      transformIndexHtml(_, ctx) {
        if (ctx.bundle) {
          // Only inject during build
          return [
            {
              tag: 'script',
              attrs: { type: 'module' },
              children: dynamicBaseAssetsCode,
            },
          ]
        }
      },
    },
  ],
  experimental: {
    renderBuiltUrl(filename, { hostType, type }) {
      if (type === 'asset') {
        if (hostType === 'js') {
          return {
            runtime: `globalThis.__toAssetUrl(${JSON.stringify(filename)})`,
          }
        }
      } else if (type === 'public') {
        if (hostType === 'js') {
          return {
            runtime: `globalThis.__publicBase+${JSON.stringify(filename)}`,
          }
        }
      }
    },
  },
  cacheDir: 'node_modules/.vite-runtime-base',
})


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

using json = nlohmann::json;

int main()
{
    // create a JSON value
    json value = { "the good", "the bad", "the ugly" };

    // create string_t
    json::string_t string = "the fast";

    // swap the object stored in the JSON value
    value[1].swap(string);

    // output the values
    std::cout << "value = " << value << '\n';
    std::cout << "string = " << string << '\n';
}


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

using json = nlohmann::json;
using namespace nlohmann::literals;

int main()
{
    json j = R"( {"hello": "world", "answer": 42} )"_json;

    std::cout << std::setw(2) << j << '\n';
}


Accept duplicated attribute

<datalist>
  <option value="option-without-closing-tag">
</datalist>

No quotes on Attr

<svg>

  <use xlink:href="/sprite.svg#svg"></use>
</svg>

<self-close-non-void />


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

using json = nlohmann::json;

int main()
{
    // create JSON array
    json array = {"first", "2nd", "third", "fourth"};

    // output element at index 2 (third element)
    std::cout << array.at(2) << '\n';

    // change element at index 1 (second element) to "second"
    array.at(1) = "second";

    // output changed array
    std::cout << array << '\n';

    // exception type_error.304
    try
    {
        // use at() on a non-array type
        json str = "I am a string";
        str.at(0) = "Another string";
    }
    catch (const json::type_error& e)
    {
        std::cout << e.what() << '\n';
    }

    // exception out_of_range.401
    try
    {
        // try to write beyond the array limit
        array.at(5) = "sixth";
    }
    catch (const json::out_of_range& e)
    {
        std::cout << e.what() << '\n';
    }
}


#include <iostream>

#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 1
#include <nlohmann/json.hpp>

// macro needed to output the NLOHMANN_JSON_NAMESPACE as string literal
#define Q(x) #x
#define QUOTE(x) Q(x)

int main()
{
    std::cout << QUOTE(NLOHMANN_JSON_NAMESPACE) << std::endl;
}


#![allow(clippy::used_underscore_binding, dead_code)]

use serde_derive::{Deserialize, Serialize};

#[test]
fn test_self() {
    pub trait Trait {
        type Assoc;
    }

    #[derive(Deserialize, Serialize)]
    pub struct Generics<T: Trait<Assoc = Self>>
    where
        Self: Trait<Assoc = Self>,
        <Self as Trait>::Assoc: Sized,
    {
        _f: T,
    }

    impl<T: Trait<Assoc = Self>> Trait for Generics<T> {
        type Assoc = Self;
    }

    #[derive(Deserialize, Serialize)]
    pub struct Struct {
        _f1: Box<Self>,
        _f2: Box<<Self as Trait>::Assoc>,
        _f4: [(); Self::ASSOC],
        _f5: [(); Self::assoc()],
    }

    impl Struct {
        const ASSOC: usize = 1;
        const fn assoc() -> usize {
            0
        }
    }

    impl Trait for Struct {
        type Assoc = Self;
    }

    #[derive(Deserialize, Serialize)]
    pub struct Tuple(
        Box<Self>,
        Box<<Self as Trait>::Assoc>,
        [(); Self::ASSOC],
        [(); Self::assoc()],
    );

    impl Tuple {
        const ASSOC: usize = 1;
        const fn assoc() -> usize {
            0
        }
    }

    impl Trait for Tuple {
        type Assoc = Self;
    }

    #[derive(Deserialize, Serialize)]
    pub enum Enum {
        Struct {
            _f1: Box<Self>,
            _f2: Box<<Self as Trait>::Assoc>,
            _f4: [(); Self::ASSOC],
            _f5: [(); Self::assoc()],
        },
        Tuple(
            Box<Self>,
            Box<<Self as Trait>::Assoc>,
            [(); Self::ASSOC],
            [(); Self::assoc()],
        ),
    }

    impl Enum {
        const ASSOC: usize = 1;
        const fn assoc() -> usize {
            0
        }
    }

    impl Trait for Enum {
        type Assoc = Self;
    }
}


import a9 from './a9'
import a10 from './a10'
import a11 from './a11'
import a12 from './a12'
import a13 from './a13'
import a14 from './a14'
import a15 from './a15'
import a16 from './a16'
import a17 from './a17'
import a18 from './a18'
import a19 from './a19'
import a20 from './a20'
import a21 from './a21'
import a22 from './a22'
import a23 from './a23'
import a24 from './a24'

export const that = () => import('./a7.js')

export function other() {
  return (
    a9() +
    a10() +
    a11() +
    a12() +
    a13() +
    a14() +
    a15() +
    a16() +
    a17() +
    a18() +
    a19() +
    a20() +
    a21() +
    a22() +
    a23() +
    a24()
  )
}

export default function () {
  return 123
}


Promise.all([import('./deps-all-accepted'), import('./deps-some-accepted')])
  .then(([all, some]) => {
    console.log('loaded:all:' + all.a + all.b + all.c + all.default)
    console.log('loaded:some:' + some.a + some.b + some.c + some.default)
    console.log('>>> ready <<<')
  })
  .catch((err) => {
    console.error(err)
  })


# Pkg-config

If you are using bare Makefiles, you can use `pkg-config` to generate the include flags that point to where the library is installed:

```sh
pkg-config nlohmann_json --cflags
```

Users of the [Meson build system](package_managers.md#meson) will also be able to use a system-wide library, which will be found by `pkg-config`:

```meson
json = dependency('nlohmann_json', required: true)
```