load("@fbsource//tools/build_defs:default_platform_defs.bzl", "ANDROID", "APPLE", "CXX", "FBCODE", "IOS", "MACOSX", "WINDOWS")
load("@fbsource//tools/build_defs:fb_native_wrapper.bzl", "fb_native")
load("@fbsource//tools/build_defs:fb_xplat_cxx_library.bzl", "fb_xplat_cxx_library")
load("@fbsource//tools/build_defs:fb_xplat_rust_library.bzl", "fb_xplat_rust_library")
load("@fbsource//tools/build_defs:fb_xplat_suffixed_aliases.bzl", "create_forwarding_aliases")
load("@fbsource//tools/build_defs:fbsource_utils.bzl", "is_fbcode_compatible", "is_fbcode_mode_mac", "is_fbcode_mode_win", "is_xplat")
load("@fbsource//tools/build_defs:rust_bindgen_library.bzl", "rust_bindgen_library")

oncall("rust_libraries")

# Avoid duplicate symbols by redirecting the top-level iobuf/iobuf-ffi targets to only one variant
# of the library. This way, we don't end up with both `fbcode//folly/rust/iobuf:iobuf` and `fbsource//xplat/folly/rust/iobuf:iobuf`
# in the same build graph.
create_forwarding_aliases(
    name = "iobuf",
    actual_name = select({
        "DEFAULT": "fbsource//xplat/folly/rust/iobuf:_iobuf",
        "ovr_config//os:linux": "fbcode//folly/rust/iobuf:_iobuf" if is_fbcode_compatible() else "fbsource//xplat/folly/rust/iobuf:_iobuf",
        "ovr_config//os:macos": "fbcode//folly/rust/iobuf:_iobuf" if is_fbcode_mode_mac() else "fbsource//xplat/folly/rust/iobuf:_iobuf",
        "ovr_config//os:windows": "fbcode//folly/rust/iobuf:_iobuf" if is_fbcode_mode_win() else "fbsource//xplat/folly/rust/iobuf:_iobuf",
    }),
    platforms = (CXX, ANDROID, APPLE, FBCODE, WINDOWS),
    sdks = (IOS, MACOSX),
    visibility = ["PUBLIC"],
) if is_xplat() else None

create_forwarding_aliases(
    name = "iobuf-ffi",
    actual_name = select({
        "DEFAULT": "fbsource//xplat/folly/rust/iobuf:_iobuf-ffi",
        "ovr_config//os:linux": "fbcode//folly/rust/iobuf:_iobuf-ffi" if is_fbcode_compatible() else "fbsource//xplat/folly/rust/iobuf:_iobuf-ffi",
        "ovr_config//os:macos": "fbcode//folly/rust/iobuf:_iobuf-ffi" if is_fbcode_mode_mac() else "fbsource//xplat/folly/rust/iobuf:_iobuf-ffi",
        "ovr_config//os:windows": "fbcode//folly/rust/iobuf:_iobuf-ffi" if is_fbcode_mode_win() else "fbsource//xplat/folly/rust/iobuf:_iobuf-ffi",
    }),
    platforms = (CXX, ANDROID, APPLE, FBCODE, WINDOWS),
    sdks = (IOS, MACOSX),
    visibility = ["PUBLIC"],
) if is_xplat() else None

rust_bindgen_library(
    name = "iobuf-sys",
    allowlist_funcs = [
        "facebook::rust::.*",
    ],
    allowlist_types = [
        "folly::IOBuf",
        "facebook::rust::.*",
    ],
    allowlist_vars = [
        "facebook::rust::.*",
    ],
    blocklist_types = [
        # These seems to come from type_traits / make_signed via fbvector
        "folly::fbvector.*",
        "__type",
        "type_",
    ],
    cpp_deps = [":_iobuf-ffi"],
    cxx_namespaces = True,
    generate = ("types", "vars", "functions"),
    header = "iobuf.h",
    opaque_types = [
        "std::.*",
        "folly::fbstring.*",
    ],
    platforms = (CXX, ANDROID, APPLE, FBCODE, WINDOWS),
    src_includes = ["iobuf_sys.rs"],
    visibility = [],
)

fb_xplat_cxx_library(
    name = "_iobuf-ffi",
    srcs = ["iobuf.cpp"],
    exported_headers = ["iobuf.h"],
    platforms = (CXX, ANDROID, APPLE, FBCODE, WINDOWS),
    preferred_linkage = "static",
    visibility = [
        "fbcode//folly/rust/iobuf/...",
        "fbsource//xplat/folly/rust/iobuf/...",
    ],
    exported_deps = [
        "fbsource//xplat/folly/io:iobuf" if is_xplat() else "fbcode//folly/io:iobuf",
    ],
)

fb_xplat_rust_library(
    name = "_iobuf",
    srcs = glob(["src/*.rs"]),
    cpp_deps = [":_iobuf-ffi"],
    crate = "iobuf",
    crate_root = "src/lib.rs",
    cxx_bridge = "src/lib.rs",
    platforms = (CXX, ANDROID, APPLE, WINDOWS),
    test_deps = [
        "fbsource//third-party/rust:quickcheck",
        "fbsource//xplat/thrift/lib/rust/src/dep_tests:test_if-rust",
    ],
    visibility = [
        "fbcode//folly/rust/iobuf/...",
        "fbsource//xplat/folly/rust/iobuf/...",
    ],
    xplat_preexisting_target_flavors = [FBCODE],
    deps = [
        "fbsource//third-party/rust:bytes",
        "fbsource//third-party/rust:cxx",
        "fbsource//third-party/rust:memmap2",
        "fbsource//xplat/thrift/lib/rust:fbthrift",
        ":iobuf-sys",
    ],
)

fb_native.alias(
    name = "_iobufFbcode",
    actual = ":_iobuf",
    visibility = [
        "fbcode//folly/rust/iobuf/...",
        "fbsource//xplat/folly/rust/iobuf/...",
    ],
) if is_xplat() else None
