// This file is for testing the binary representation of options in protocompile,
// to make sure it matches the representation used by protoc. To that end, this
// file contains lots of interesting (seemingly haphazard) options and
// de-structuring of custom options.
//
// This files defines many options, in various forms (destructured and not) and
// orders (including for packed and non-packed repeated fields). It is defined
// as proto2 so that we can also test extension range options.
syntax = "proto2";

package bufbuild.protocompile.test;

import "options.proto";
// We don't need to explicitly import google/protobuf/descriptor.proto since
// the customizations (extra non-custom enum options) are pulled in
// implicitly by options.proto.

option (file_i) = 1;
option (file_i) = 2;
option (file_i) = 3;

message TestMessage {
  option (msg_i) = 1;
  option (msg_i) = 2;
  option (msg_i) = 3;

  optional string foo = 1 [default = "xyz", json_name = "FOO"];
  optional int32 bar = 2 [json_name = "bAr", default = 314];
  repeated bool baz = 3 [json_name = "Baz"];

  optional string _field_ = 4 [
    (fld_i) = 1,
    (fld_i) = 2,
    (fld_i) = 3,

    (fld) = {
      i32: 0 i64: 1 u32: 2 u64: 3
      f32: 4 f64: 5 sf32: 6 sf64: 7
      fl32: 8.9 fl64: 9.101 s32: -10 s64: -11
      str: "file"

      oo_i32: -9876
      oo_f32: 1234
      oo_fl32: 1.2345e100
      oo_b: "\x00\x01\x02\x03"
    },

    (fld).r_s32 = 0,
    (fld).r_s32 = 1,

    (fld).pr_s32 = 0,
    (fld).pr_s32 = 1,

    (fld).m_s32 = {
      key: 123,
      value: 0
    },
    (fld).m_s32 = {
      key: -234,
      value: 1
    },

    (fld).flag = true,
    (fld).b = "\x00\x01\x02\x03",
    (fld).grp = {
      foo: "abc" bar: 999
    },

    (fld).r_fl32 = 0,
    (fld).r_fl32 = 1,

    (fld).pr_fl32 = 0,
    (fld).pr_fl32 = 1,

    (fld).m_fl32 = {
      key: "abc",
      value: 0
    },
    (fld).m_fl32 = {
      key: "def",
      value: 1
    },

    (fld).r_msg = {
      foo: "filefoo", bar: 99, baz: false
    },

    (fld).r_msg = {
      foo: "filefoo2", bar: 98, baz: true
    },

    (fld).msg.(t) = {
      r_s32: [0, 1, 2, 3]
      pr_s32: [0, 1, 2, 3]
      m_s32: [
        { key: 123, value: 1 }, { key: -234, value: 2 }
      ]
      r_fl32: [0, 1, 2, 3]
      pr_fl32: [0, 1, 2, 3]
      m_fl32: [
        { key: "foo", value: 1 }, { key: "bar", value: 2 }
      ]
    },
    (fld).msg.(t).msg.(t) = {
      r_s32: 1
      r_s32: 2
      pr_s32: 1
      pr_s32: 2
      m_s32: { value: 0 }
      m_s32: { key: 123, value: 1 }
      m_s32: { key: 234, value: 2 }
      m_s32: { key: -345 }
      r_fl32: 1
      r_fl32: 2
      pr_fl32: 1
      pr_fl32: 2
      m_fl32: { }
      m_fl32: { key: "bar", value: -2.2222 }
    }
  ];

  oneof _oo_ {
    option (oo_i) = 1;
    option (oo_i) = 2;
    option (oo_i) = 3;

    int32 ii = 10;
    uint32 uu = 11;
    sint32 ss = 12;

    option (oo) = {
      i32: 0 i64: 1 u32: 2 u64: 3
      f32: 4 f64: 5 sf32: 6 sf64: 7
      fl32: 8.9 fl64: 9.101 s32: -10 s64: -11
      str: "file"
    };

    option (oo).oo_i64 = -9876;
    option (oo).oo_f64 = 1234;
    option (oo).oo_fl64 = 1.2345e100;
    option (oo).oo_str = "foobar";

    option (oo).r_i64 = 0;
    option (oo).r_i64 = 1;

    option (oo).pr_i64 = 0;
    option (oo).pr_i64 = 1;

    option (oo).m_i64 = {
      key: 123
      value: 0
    };
    option (oo).m_i64 = {
      key: -234
      value: 1
    };

    option (oo).flag = true;
    option (oo).b = "\x00\x01\x02\x03";
    option (oo).grp = {
      foo: "abc" bar: 999
    };

    option (oo).r_u64 = 0;
    option (oo).r_u64 = 1;

    option (oo).pr_u64 = 0;
    option (oo).pr_u64 = 1;

    option (oo).m_u64 = {
      key: 123
      value: 0
    };
    option (oo).m_u64 = {
      key: 234
      value: 1
    };

    option (oo).r_msg = {
      foo: "filefoo", bar: 99, baz: false
    };

    option (oo).r_msg = {
      foo: "filefoo2", bar: 98, baz: true
    };

    option (oo).msg.(t) = {
      r_i64: [0, 1, 2, 3]
      pr_i64: [0, 1, 2, 3]
      m_i64: [
        { key: 123, value: 1 }, { key: 234, value: 2 }
      ]
      r_u64: [0, 1, 2, 3]
      pr_u64: [0, 1, 2, 3]
      m_u64: [
        { key: 123, value: 1 }, { key: 234, value: 2 }
      ]
    };
    option (oo).msg.(t).msg.(t) = {
      r_i64: 1
      r_i64: 2
      pr_i64: 1
      pr_i64: 2
      m_i64: { value: 0 }
      m_i64: { key: 123, value: 1 }
      m_i64: { key: 234, value: 2 }
      m_i64: { key: -345 }
      r_u64: 1
      r_u64: 2
      pr_u64: 1
      pr_u64: 2
      m_u64: { }
      m_u64: { key: 234, value: 2 }
    };
  }

  extensions 100 to max [
    (ext_i) = 1,
    (ext_i) = 2,
    (ext_i) = 3,

    (ext) = {
      i32: 0 i64: 1 u32: 2 u64: 3
      f32: 4 f64: 5 sf32: 6 sf64: 7
      fl32: 8.9 fl64: 9.101 s32: -10 s64: -11
      str: "file"

      oo_s32: -9876
      oo_sf32: 1234
      oo_flag: true
      oo_msg <foo: "abc" bar: 123>
    },

    (ext).r_f32 = 0,
    (ext).r_f32 = 1,

    (ext).pr_f32 = 0,
    (ext).pr_f32 = 1,

    (ext).m_f32 = {
      key: 123,
      value: 0
    },
    (ext).m_f32 = {
      key: 234,
      value: 1
    },

    (ext).flag = true,
    (ext).b = "\x00\x01\x02\x03",
    (ext).grp = {
      foo: "abc" bar: 999
    },

    (ext).r_sf32 = 0,
    (ext).r_sf32 = 1,

    (ext).pr_sf32 = 0,
    (ext).pr_sf32 = 1,

    (ext).m_sf32 = {
      key: 123,
      value: 0
    },
    (ext).m_sf32 = {
      key: -234,
      value: 1
    },

    (ext).r_msg = {
      foo: "filefoo", bar: 99, baz: false
    },

    (ext).r_msg = {
      foo: "filefoo2", bar: 98, baz: true
    },

    (ext).msg.(t) = {
      r_f32: [0, 1, 2, 3]
      pr_f32: [0, 1, 2, 3]
      m_f32: [
        { key: 123, value: 1 }, { key: 234, value: 2 }
      ]
      r_sf32: [0, 1, 2, 3]
      pr_sf32: [0, 1, 2, 3]
      m_sf32: [
        { key: 123, value: 1 }, { key: 234, value: 2 }
      ]
    },
    (ext).msg.(t).msg.(t) = {
      r_f32: 1
      r_f32: 2
      pr_f32: 1
      pr_f32: 2
      m_f32: { value: 0 }
      m_f32: { key: 123, value: 1 }
      m_f32: { key: 234, value: 2 }
      m_f32: { key: 345 }
      r_sf32: 1
      r_sf32: 2
      pr_sf32: 1
      pr_sf32: 2
      m_sf32: { }
      m_sf32: { key: -234, value: 2 }
    }
  ];

  option (msg) = {
    i32: 0 i64: 1 u32: 2 u64: 3
    f32: 4 f64: 5 sf32: 6 sf64: 7
    fl32: 8.9 fl64: 9.101 s32: -10 s64: -11
    str: "file"
  };

  option (msg).oo_s64 = -9876;
  option (msg).oo_sf64 = 1234;
  option (msg).oo_en = UNO;
  option (msg).oo_grp = { foo: "abc" bar: 123 };

  option (msg).r_f32 = 0;
  option (msg).r_f32 = 1;

  option (msg).pr_f32 = 0;
  option (msg).pr_f32 = 1;

  option (msg).m_f32 = {
    key: 123
    value: 0
  };
  option (msg).m_f32 = {
    key: 234
    value: 1
  };

  option (msg).flag = true;
  option (msg).b = "\x00\x01\x02\x03";
  option (msg).grp = {
    foo: "abc" bar: 999
  };

  option (msg).r_sf32 = 0;
  option (msg).r_sf32 = 1;

  option (msg).pr_sf32 = 0;
  option (msg).pr_sf32 = 1;

  option (msg).m_sf32 = {
    key: 123
    value: 0
  };
  option (msg).m_sf32 = {
    key: -234
    value: 1
  };

  option (msg).r_msg = {
    foo: "filefoo", bar: 99, baz: false
  };

  option (msg).r_msg = {
    foo: "filefoo2", bar: 98, baz: true
  };

  option (msg).msg.(t) = {
    r_f32: [0, 1, 2, 3]
    pr_f32: [0, 1, 2, 3]
    m_f32: [
      { key: 123, value: 1 }, { key: 234, value: 2 }
    ]
    r_sf32: [0, 1, 2, 3]
    pr_sf32: [0, 1, 2, 3]
    m_sf32: [
      { key: 123, value: 1 }, { key: 234, value: 2 }
    ]
  };
  option (msg).msg.(t).msg.(t) = {
    r_f32: 1
    r_f32: 2
    pr_f32: 1
    pr_f32: 2
    m_f32: { value: 0 }
    m_f32: { key: 123, value: 1 }
    m_f32: { key: 234, value: 2 }
    m_f32: { key: 345 }
    r_sf32: 1
    r_sf32: 2
    pr_sf32: 1
    pr_sf32: 2
    m_sf32: { }
    m_sf32: { key: -234, value: -2 }
  };

  option message_set_wire_format = false;
}

option (file) = {
  i32: 0 i64: 1 u32: 2 u64: 3
  f32: 4 f64: 5 sf32: 6 sf64: 7
  fl32: 8.9 fl64: 9.101 s32: -10 s64: -11
  str: "file"

  oo_u32: 9876
  oo_f32: 1234
  oo_fl32: 1.2345e100
  oo_b: "\x00\x01\x02\x03"
};

option (file).r_i32 = 0;
option (file).r_i32 = 1;

option (file).pr_i32 = 0;
option (file).pr_i32 = 1;

option (file).m_i32 = {
  key: 123
  value: 0
};
option (file).m_i32 = {
  key: -234
  value: 1
};

option (file).flag = true;
option (file).b = "\x00\x01\x02\x03";
option (file).grp = {
  foo: "abc" bar: 999
};

option (file).r_u32 = 0;
option (file).r_u32 = 1;

option (file).pr_u32 = 0;
option (file).pr_u32 = 1;

option (file).m_u32 = {
  key: 123
  value: 0
};
option (file).m_u32 = {
  key: 234
  value: 1
};

option (file).r_msg = {
  foo: "filefoo", bar: 99, baz: false
};

option (file).r_msg = {
  foo: "filefoo2", bar: 98, baz: true
};

enum TestEnum {
  option bar = 3.14159;
  option foo = "Bob Loblaw";

  option allow_alias = true;

  option baz = "Tobias Funke";
  option deprecated = false;

  option (en_i) = 1;
  option (en_i) = 2;
  option (en_i) = 3;

  ZED = 0 [deprecated = true];
  NULL = 0;

  UNO = 1 [
    (env_i) = 1,
    (env_i) = 2,
    (env_i) = 3,

    (env) = {
      i32: 0 i64: 1 u32: 2 u64: 3
      f32: 4 f64: 5 sf32: 6 sf64: 7
      fl32: 8.9 fl64: 9.101 s32: -10 s64: -11
      str: "file"
    },

    (env).oo_u32 = 9876,
    (env).oo_f32 = 1234,
    (env).oo_fl32 = 1.2345e100,
    (env).oo_b = "\x00\x01\x02\x03",

    (env).r_s64 = 0,
    (env).r_s64 = 1,

    (env).pr_s64 = 0,
    (env).pr_s64 = 1,

    (env).m_s64 = {
      key: 123,
      value: 0
    },
    (env).m_s64 = {
      key: -234,
      value: 1
    },

    (env).flag = true,
    (env).b = "\x00\x01\x02\x03",
    (env).grp = {
      foo: "abc" bar: 999
    },

    (env).r_fl64 = 0,
    (env).r_fl64 = 1,

    (env).pr_fl64 = 0,
    (env).pr_fl64 = 1,

    (env).m_fl64 = {
      key: "abc",
      value: 0
    },
    (env).m_fl64 = {
      key: "def",
      value: 1
    },

    (env).r_msg = {
      foo: "filefoo", bar: 99, baz: false
    },

    (env).r_msg = {
      foo: "filefoo2", bar: 98, baz: true
    },

    (env).msg.(t) = {
      r_s64: [0, 1, 2, 3]
      pr_s64: [0, 1, 2, 3]
      m_s64: [
        { key: 123, value: 1 }, { key: 234, value: 2 }
      ]
      r_fl64: [0, 1, 2, 3]
      pr_fl64: [0, 1, 2, 3]
      m_fl64: [
        { key: "foo", value: 1 }, { key: "bar", value: 2 }
      ]
    },
    (env).msg.(t).msg.(t) = {
      r_s64: 1
      r_s64: 2
      pr_s64: 1
      pr_s64: 2
      m_s64: { value: 0 }
      m_s64: { key: 123, value: 1 }
      m_s64: { key: 234, value: 2 }
      m_s64: { key: -345 }
      r_fl64: 1
      r_fl64: 2
      pr_fl64: 1
      pr_fl64: 2
      m_fl64: { }
      m_fl64: { key: "bar", value: 2 }
    }
  ];

  option (en) = {
    i32: 0 i64: 1 u32: 2 u64: 3
    f32: 4 f64: 5 sf32: 6 sf64: 7
    fl32: 8.9 fl64: 9.101 s32: -10 s64: -11
    str: "file"

    oo_u64: 9876
    oo_f32: 1234
    oo_fl32: 1.2345e100
    oo_b: "\x00\x01\x02\x03"
  };

  option (en).r_f64 = 0;
  option (en).r_f64 = 1;

  option (en).pr_f64 = 0;
  option (en).pr_f64 = 1;

  option (en).m_f64 = {
    key: 123
    value: 0
  };
  option (en).m_f64 = {
    key: 234
    value: 1
  };

  option (en).flag = true;
  option (en).b = "\x00\x01\x02\x03";
  option (en).grp = {
    foo: "abc" bar: 999
  };

  option (en).r_sf64 = 0;
  option (en).r_sf64 = 1;

  option (en).pr_sf64 = 0;
  option (en).pr_sf64 = 1;

  option (en).m_sf64 = {
    key: 123
    value: 0
  };
  option (en).m_sf64 = {
    key: -234
    value: 1
  };

  option (en).r_msg = {
    foo: "filefoo", bar: 99, baz: false
  };

  option (en).r_msg = {
    foo: "filefoo2", bar: 98, baz: true
  };

  option (en).msg.(t) = {
    r_f64: [0, 1, 2, 3]
    pr_f64: [0, 1, 2, 3]
    m_f64: [
      { key: 123, value: 1 }, { key: 234, value: 2 }
    ]
    r_sf64: [0, 1, 2, 3]
    pr_sf64: [0, 1, 2, 3]
    m_sf64: [
      { key: 123, value: 1 }, { key: 234, value: 2 }
    ]
  };
  option (en).msg.(t).msg.(t) = {
    r_f64: 1
    r_f64: 2
    pr_f64: 1
    pr_f64: 2
    m_f64: { value: 0 }
    m_f64: { key: 123, value: 1 }
    m_f64: { key: 234, value: 2 }
    m_f64: { key: 345 }
    r_sf64: 1
    r_sf64: 2
    pr_sf64: 1
    pr_sf64: 2
    m_sf64: { }
    m_sf64: { key: -234, value: -2 }
  };
}

option (file).msg.(t) = {
  r_i32: [0, 1, 2, 3]
  pr_i32: [0, 1, 2, 3]
  m_i32: [
    { key: 123, value: 1 }, { key: 234, value: 2 }
  ]
  r_u32: [0, 1, 2, 3]
  pr_u32: [0, 1, 2, 3]
  m_u32: [
    { key: 123, value: 1 }, { key: 234, value: 2 }
  ]
};
option (file).msg.(t).msg.(t) = {
  r_i32: 1
  r_i32: 2
  pr_i32: 1
  pr_i32: 2
  m_i32: { value: 0 }
  m_i32: { key: 123, value: 1 }
  m_i32: { key: 234, value: 2 }
  m_i32: { key: -345 }
  r_u32: 1
  r_u32: 2
  pr_u32: 1
  pr_u32: 2
  m_u32: { }
  m_u32: { key: 234, value: 2 }
};

extend Extendable {
  optional string s_s_s = 200 [
    (fld_i) = 1,
    (fld_i) = 2,
    (fld_i) = 3,

    (fld) = {
      i32: 0 i64: 1 u32: 2 u64: 3
      f32: 4 f64: 5 sf32: 6 sf64: 7
      fl32: 8.9 fl64: 9.101 s32: -10 s64: -11
      str: "file"
    },

    (fld).oo_u64 = 9876,
    (fld).oo_f32 = 1234,
    (fld).oo_fl32 = 1.2345e100,
    (fld).oo_b = "\x00\x01\x02\x03",

    (fld).r_grp = {foo: "foo"},
    (fld).r_grp = {foo: "bar"},

    (fld).m_s32 = {
      key: 123,
      value: 0
    },
    (fld).m_s32 = {
      key: -234,
      value: 1
    },

    (fld).flag = true,
    (fld).b = "\x00\x01\x02\x03",
    (fld).grp = {
      foo: "abc" bar: 999
    },

    (fld).r_fl32 = 0,
    (fld).r_fl32 = 1,

    (fld).pr_fl32 = 0,
    (fld).pr_fl32 = 1,

    (fld).m_fl32 = {
      key: "abc",
      value: 0
    },
    (fld).m_fl32 = {
      key: "def",
      value: 1
    },

    (fld).r_msg = {
      foo: "filefoo", bar: 99, baz: false
    },

    (fld).r_msg = {
      foo: "filefoo2", bar: 98, baz: true
    },

    (fld).msg.(t) = {
      R_Grp: [
        <foo:"a", bar:1>, <foo:"b", bar:2>, <foo:"c", bar:3>
      ]
      m_grp: [
        { key: "foo", value: <foo:"foo"> }, { key: "bar", value: <foo:"bar"> }
      ]
      r_fl32: [0, 1, 2, 3]
      pr_fl32: [0, 1, 2, 3]
      m_fl32: [
        { key: "foo", value: 1 }, { key: "bar", value: 2 }
      ]
    },
    (fld).msg.(t).msg.(t) = {
      R_Grp: <foo: "a", bar: 1>
      R_Grp: <foo: "b", bar: 2>
      m_grp: { value: <foo: "abc", bar: 123> }
      m_grp: { key: "1", value: <foo: "def", bar: 234> }
      m_grp: { key: "2", value: <foo: "ghi", bar: 345> }
      m_grp: { key: "3" }
      r_fl32: 1
      r_fl32: 2
      pr_fl32: 1
      pr_fl32: 2
      m_fl32: { }
      m_fl32: { key: "bar", value: -2.22222 }
    }
  ];
}

service TestService {
  option (svc_i) = 1;
  option (svc_i) = 2;
  option (svc_i) = 3;

  rpc Method(TestMessage) returns (TestMessage) {
    option (rpc_i) = 1;
    option (rpc_i) = 2;
    option (rpc_i) = 3;

    option (rpc) = {
      i32: 0 i64: 1 u32: 2 u64: 3
      f32: 4 f64: 5 sf32: 6 sf64: 7
      fl32: 8.9 fl64: 9.101 s32: -10 s64: -11
      str: "file"

      oo_i32: -9876
      oo_f32: 1234
      oo_fl32: 1.2345e100
      OO_Grp <foo: "abc" bar: 123>
    };

    option (rpc).r_en = ZED;
    option (rpc).r_en = UNO;

    option (rpc).pr_en = ZED;
    option (rpc).pr_en = UNO;

    option (rpc).m_en = {
      key: "abc"
      value: ZED
    };
    option (rpc).m_en = {
      key: "def"
      value: UNO
    };

    option (rpc).flag = true;
    option (rpc).b = "\x00\x01\x02\x03";
    option (rpc).grp = {
      foo: "abc" bar: 999
    };

    option (rpc).r_str = "abc";
    option (rpc).r_str = "def";

    option (rpc).m_str = {
      key: "abc"
      value: "zero"
    };
    option (rpc).m_str = {
      key: "def"
      value: "one"
    };

    option (rpc).r_msg = {
      foo: "filefoo", bar: 99, baz: false
    };

    option (rpc).r_msg = {
      foo: "filefoo2", bar: 98, baz: true
    };

    option (rpc).msg.(t) = {
      r_en: [ZED, UNO, DOS]
      pr_en: [ZED, UNO, DOS]
      m_en: [
        { key: "foo", value: UNO }, { key: "bar", value: DOS }
      ]
      r_str: ["abc", "def", "mno", "xyz"]
      m_str: [
        { key: "foo", value: "one" }, { key: "bar", value: "two" }
      ]
    };
    option (rpc).msg.(t).msg.(t) = {
      r_en: UNO
      r_en: DOS
      pr_en: UNO
      pr_en: DOS
      m_en: { key: "foo", value: UNO }
      m_en: { key: "bar", value: DOS }
      r_str: "abc"
      r_str: "def"
      m_str: { key: "foo", value: "one" }
      m_str: { key: "bar", value: "two" }
    };
  }

  option (svc) = {
    i32: 0 i64: 1 u32: 2 u64: 3
    f32: 4 f64: 5 sf32: 6 sf64: 7
    fl32: 8.9 fl64: 9.101 s32: -10 s64: -11
    str: "file"
  };

  option (svc).oo_i32 = -9876;
  option (svc).oo_f32 = 1234;
  option (svc).oo_fl32 = 1.2345e100;
  option (svc).oo_b = "\x00\x01\x02\x03";

  option (svc).r_flag = true;
  option (svc).r_flag = false;

  option (svc).pr_flag = true;
  option (svc).pr_flag = false;

  option (svc).m_flag = {
    key: "abc"
    value: true
  };
  option (svc).m_flag = {
    key: "def"
    value: false
  };

  option (svc).flag = true;
  option (svc).b = "\x00\x01\x02\x03";
  option (svc).grp = {
    foo: "abc" bar: 999
  };

  option (svc).r_b = "\x00\x01";
  option (svc).r_b = "\x02\x03";

  option (svc).r_grp = {
    foo: "foo", bar: 1
  };
  option (svc).r_grp = {
    foo: "bar", bar: 2
  };

  option (svc).m_b = {
    key: "abc"
    value: "\x00\x01"
  };
  option (svc).m_b = {
    key: "def"
    value: "\x02\x03"
  };

  option (svc).r_msg = {
    foo: "filefoo", bar: 99, baz: false
  };
  option (svc).r_msg = {
    foo: "filefoo2", bar: 98, baz: true
  };

  option (svc).msg.(t) = {
    r_flag: [true, true, false, false]
    pr_flag: [false, false, true, true]
    m_flag: [
      { key: "foo", value: true }, { key: "bar", value: false }
    ]
    r_b: ["abc", "def", "mno", "xyz"]
    m_b: [
      { key: "foo", value: "abc" }, { key: "bar", value: "def" }
    ]
  };
  option (svc).msg.(t).msg.(t) = {
    r_flag: true
    r_flag: false
    pr_flag: true
    pr_flag: false
    m_flag: { key: "foo", value: true }
    m_flag: { key: "bar", value: false }
    r_b: "abc"
    r_b: "def"
    m_b: { key: "foo", value: "abc" }
    m_b: { key: "bar", value: "def" }
  };

  option deprecated = true;
}

option go_package = "foo";
option java_package = "bar";
