diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:42 +0000 |
commit | 837b550238aa671a591ccf282dddeab29cadb206 (patch) | |
tree | 914b6b8862bace72bd3245ca184d374b08d8a672 /vendor/cxx | |
parent | Adding debian version 1.70.0+dfsg2-1. (diff) | |
download | rustc-837b550238aa671a591ccf282dddeab29cadb206.tar.xz rustc-837b550238aa671a591ccf282dddeab29cadb206.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/cxx')
234 files changed, 13877 insertions, 0 deletions
diff --git a/vendor/cxx/.cargo-checksum.json b/vendor/cxx/.cargo-checksum.json new file mode 100644 index 000000000..45af3b5ca --- /dev/null +++ b/vendor/cxx/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"BUCK":"b2259ccff14070b10350af72aff96a04fe6dbfbd8d5116aae26cb989b7bf9d6f","BUILD":"73011fc75cb254ad0f2abe6b842eb6f625397d8aa82da929e6431087d3b2a005","Cargo.toml":"4ef76b1bf9d493bfc075a140dbba327f7f5a60c0bfac4ed96be9c2d50041906b","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"db53378311b443bfee0b6635c14723584fb131ea8c3ab01aaeefe17121fb2c1c","WORKSPACE":"62198be804897c8b21508e0ea6486873b2f67d27e8baa524d91374a82e8cef59","book/README.md":"1e9d290fc6a74227878726fc29a531612c3db9f4cb619ffed941fd32b47e4726","book/book.toml":"795589687baa12c59957980eabde548b62e58498a75ce97fe5b22eb4bb8da97d","book/build.js":"02edc38bdde31b375fca3a6be946730772287899ba515af53d9d07abf8b66e4a","book/build.sh":"fc0dc29ef942a380a6fb92366438501041ebdf950f603864df0516f6162acfcd","book/css/cxx.css":"fb20396fc2d3f0479273fed3e4fbc63a767496554e84b503e3ddc6cc9396b57c","book/diagram/Makefile":"1227f53515c7fd49ceb6648fa4942a43df0c7838bc6a9d29dd23d7e7cda8cfed","book/diagram/overview.tex":"96d0ba358d640533a31b62a8e8d710b0cd72b81c55d2dbe76a14482bf7e82212","book/package-lock.json":"8076db3d66987fbf21789b8ec018caa7870d714d6f9377e82a88b62b6d3c6a64","book/package.json":"fc1b7ec59630fae3850e29dea97b5dca5de7002c1569084a5179afc47dbbf9c7","book/src/404.md":"5ee9b5acef4e5df4e895cc54002f498f2274cc4a5784434adda432e0477b933a","book/src/SUMMARY.md":"38c4df00a65d330cec0850d55a576da9219f8a7946a3c352cb797985c73a6219","book/src/async.md":"047cc5e4117fbb32960676f1a7ac790ea16eb67c226a8371017f33102da43711","book/src/attributes.md":"f98386ef20ef0cc545da9fee82099652221c6a9caf166767a1d42a7280f1a125","book/src/binding/box.md":"a2ac44c9bd676dcca1308ffeabc9aa0e93608ba71caf6cccb061abc19de22ad2","book/src/binding/cxxstring.md":"4c5e5c00a843986b11c9385fe2b471757ba0fbd6746f3ef09730c0b21321cbe2","book/src/binding/cxxvector.md":"3e196a4e3df99e20f141ce0de2021d4fec4e357c0b9f8ed7715a80d2bdb0720d","book/src/binding/fn.md":"11d679cfebb40fbf42ab969584b1215d6e46ba89ae9f2a35f3a4311bccb39940","book/src/binding/rawptr.md":"6a753ae2e4cae73f023c3f38d36488096b823e04d035a878f7748dd680a0adb6","book/src/binding/result.md":"587dcc027c0fc379cdc7bd5abefdcdb1edbd4b9a88c3b8becd42c1ddf0717516","book/src/binding/sharedptr.md":"305a4e850ce5c778bc97105b8ada6c817fc7fd78cecf75c2ecce4417465d3d10","book/src/binding/slice.md":"8ea1d26b1e26f7120427e2bb1baa613d924068bbae0276423494d9afc6fd7301","book/src/binding/str.md":"ae7c79f5b40a759b3ad1cd877158062903efe558994d329273ac1e0a13beaf32","book/src/binding/string.md":"64df7b816ac67c62f9e82815433bd405d7587b96163c3ed22467663f95e102d7","book/src/binding/uniqueptr.md":"5525885a85f1e945082c3461a65ace4a10d229e505a935ae447ba72a9844fee9","book/src/binding/vec.md":"44b7b9d4a812cb49202e0ef408a8b7e6a918c614369e75347078be0b319a6445","book/src/bindings.md":"2f2bdfc2f36305ead48797f44958d88e98c08083244bdcf3895e21c9d4c3b686","book/src/build/bazel.md":"9540a85fc35f21b17e0e359d2d0046e6284c6c98ee823d8e93b84776d5d57df2","book/src/build/cargo.md":"1a0ed39fb5d7a0cf805d49af0e9c8fe4de4e16388831ae2ab2a3d1f3959ccafa","book/src/build/cmake.md":"b92ee62866fa9741ce953b106a0568d5942e7e066dc35f7b44b3aac25fa9a994","book/src/build/other.md":"80d105c8182859f190345a8ed4aaa8142d2e0a832d1fc4f8cb6de634a6994f71","book/src/building.md":"e75f3f65992e4ec558f050ee554f7f09d4f2967a9ec7f4a6d1506529a649ce74","book/src/concepts.md":"d3e362a8d77dd9b6835c09d2cc10e1ebf9f326ff7b09b3d0235c6294564add6d","book/src/context.md":"4ecaab2550141c57211db1cc8e6869a9a36ab2a86aa6dffbaaae2670e7599551","book/src/cxx.png":"0d5cd8e1e396e937d0ae340ad7b2709a7001a4dfc36a2754fae4240b84b7fbb0","book/src/extern-c++.md":"e94d02d630d272d342df9c365d155d17424ed5e49147f11eb37c4c330ad51672","book/src/extern-rust.md":"5d54e52e20f60e6c51610114554602b02d6da8436a1d03ba64a6267043bc39a0","book/src/index.md":"50feefa0ba43578e9963fa2e1d9084b5eded114125ed2c9455fd845253469633","book/src/overview.svg":"97a609c9e585ecb424b1fb5d26df38f0162cfc10ed18cc9c46c8316a7aa87712","book/src/reference.md":"a9757a50a6c878d0294fb7bd544ab702a977e938a53484a346b1fe2821860ffb","book/src/shared.md":"f3c1f8db6ab5868cf5e784afce06ffa40dcdd2a5a25d5a66064f6b9ce3427a01","book/src/tutorial.md":"c2941ce9873c91fd97df0babcc9fbfe75f279d7f477a02f78f4ccfc5055eda5f","book/theme/head.hbs":"28a07d35be7284f375f1ecae1405ff2c626e7b361cc090563376fb789dffc85f","build.rs":"0c8ec2e9d2eda54d78c10a53bc97bb363ca8af4171c85b23e5398955d8a98afc","compile_flags.txt":"8b396f7be81d9bbe82848f347427ee536c4d391876944399cda0789dbf2a5a38","include/cxx.h":"15a9c03e125858151c8ccb7b56a88fc8c3fc9acac63891def1f29364ee7066c0","src/c_char.rs":"e575d1b3c88970fd2e3b3a2536c6509dd3d6a4fde4e99a9dfb0053df2a7bafa3","src/cxx.cc":"51ff19321afa172d146cebc48f48ba110f70964985f0f9c664a2d3805f401469","src/cxx_string.rs":"91937ea7b909591058582fe192898b63fc6be93fc492a02576ac740b42691fc0","src/cxx_vector.rs":"176652e15e50f406c80b10a161a1a49d6c6e9195c2e1d6a102c58a90d2f74c7a","src/exception.rs":"67b99152a3a7adff1238ad3a6c6a65e7da5a4b3ddad79a5b0f7516348b96d5a8","src/extern_type.rs":"835c553b2b1623d9df4bf5f583f6032a159e5d2bf303c82cd0b136d80803d0bc","src/fmt.rs":"b75c8b10290e97520e74b532721e352a62453fdd0072e7908c65a384e93db19d","src/function.rs":"8601e7fcaabb52fd9df9a5a7d31d44ef2cad2e4e2f2c1eddbe3362b6e1cf4c08","src/hash.rs":"7e73decddf5033ad20cea406262ccfcb3cd84d3ca91e189eb6e550eec390b9e9","src/lib.rs":"30708aaf487432ebddf19c204e4719eff33313a84cef7ab0c4d754bac0a0fa21","src/lossy.rs":"0af5e23f76042293ec6cd6373c9a22c121d195c93d78e58fe67341537ba15d0b","src/macros/assert.rs":"1bbe8abb6d18979ff18f52af6c65209ca3f07926ddfdf3d4faf41d45179ae35a","src/macros/concat.rs":"2b29c316d1ca386abbe9c2b4b41bb010ed5c66e65732c7ddf1bee78df09b8682","src/macros/mod.rs":"2c621b8d6e1e54006451f5cb80597a95408bb1db255282990c691c4cdfece7db","src/memory.rs":"5e9045c3b0b37d2f51efffe7d3b197a119b138143964bde95a78d6d44bc73887","src/opaque.rs":"93f9644c726901b67699fab4ee6c7e5a60b20568b917d116b353ee7bad9ae51c","src/result.rs":"6a783ef9189d9b03cfe691aaf439566e881e8c6b4e0b4c6fe1e33b084de46981","src/rust_slice.rs":"6be93bfd91d7c9e455e82b16ab0d287b386ac6d4b95d5ec5c19a0353f6ea7ac6","src/rust_str.rs":"de079536b2865fb9e23f180cb6b6ab7eba51634702323bc35b779b4b4ad8578f","src/rust_string.rs":"e7d232bf8cfed41f1e1a01d45ae0d3120927bbf24dd590ba8f1b7bad3d2ccb72","src/rust_type.rs":"10ec0cb0c6ceda04dd31fe8ecef2dc57a2677a126be335568d6bbbf90b435365","src/rust_vec.rs":"883d1b6523830eb6b79ca02f4ff2cca99db798a0cd048178b6c5b95a5f91296d","src/shared_ptr.rs":"8483f3acf0f8905a06fd6587df86f3c111aac9a407d072fc37ff989f200d9b56","src/sip.rs":"ca2a6b7df514edb6c5a66c1209426bcbabe1a654a5bd611555169e300672d337","src/symbols/exception.rs":"2c6649cbc6ed8c5d2d9f90cb9eab27510ab2f961adc954628a91685ed0ab1dbe","src/symbols/mod.rs":"d8e701f172fff4bca08337fd1fd26140918411679db9d725bf3818585a94d6d8","src/symbols/rust_slice.rs":"d1fb908f1316f570a0e37bb1b568a09d7f419ef78a2ee7959bb18885bdf0a0fc","src/symbols/rust_str.rs":"432801eac891e28fc06bc21ec2c0da293cade9f1a433b87a988184882a5c2838","src/symbols/rust_string.rs":"60b4ecdad3da9fbe0e54c659e898f0457fb36cac9d2005be92b546adac0c4e87","src/symbols/rust_vec.rs":"d8959414b4606c0ac393613d9c52c98e071bbfed684f180ecee2c6243e469db0","src/type_id.rs":"535ca3905c7fff6d1714b51e5ae10d9c1008c1e5b2b570760cc8713e300be00c","src/unique_ptr.rs":"81e35cd797080ccddee218658bb4b608645e3daf4ad17f7de7ecb5464ee13e44","src/unwind.rs":"52b17e57f1b6b8c24a731fbdca15b3701139d1b1abd1671e557ef6f40ad5b18a","src/vector.rs":"6a0e8b4be72d2ddd02a85184215d2f09493df0dc21ab3c003fdad659dd72756f","src/weak_ptr.rs":"428f53f12c93e10f76f9843b27114ed1cb3080c60a4ba516305630909ba12b9d","tests/BUCK":"d336f8983f9be50d6a36d2f76ec4a9a310a3f6a1be0081ea989477682d0223f8","tests/BUILD":"544b8707b6ad9ba96ec75afaed3f4c7e0cc115e2e736f3129d913a2ee1ab0bb0","tests/compiletest.rs":"d6eafab19b31e69439cfc19b422c2f79c6ba63d16e37b5880d4f94c5d83285e1","tests/cxx_gen.rs":"33230ddb8472907e85e3fc92028e05b4f9b2629c37673d4da1a368bd51626be9","tests/cxx_string.rs":"3cb230e7c1794ee8c29b72233fc6a89296bee23b7eacb7801887e318067b4514","tests/test.rs":"5d5fe593d1e3441fd44a66b8a188bedc9afdfb2ec6801ac485ab13aae552980c","tests/ui/array_len_expr.rs":"0153a9bb662b2b271f1e7371fb6f39dd44d7474fcfd1dea43e49e72be884695c","tests/ui/array_len_expr.stderr":"d8cc40fddd8de44858995abda7a26725aaf5aa39f31d1dd6296fdc06774dd17d","tests/ui/array_len_suffix.rs":"d4770fa34972549ad1545392520fa577b114c54782655f591de41c67349fe12a","tests/ui/array_len_suffix.stderr":"2ded9e94c1a3bc918e90c71011e5fdc3c62e58463da59dc343da8d37ed9bc4c2","tests/ui/async_fn.rs":"333c6fa709b8cb4ed15b64789df55d0202ed893face1fb09e7f03178defb251d","tests/ui/async_fn.stderr":"7034b73a86fc55d332be2f9ef4d8f7b3e0d7865f562018ef676bf4d68a06f67d","tests/ui/bad_explicit_impl.rs":"93cf7ce33d98037202e3422d8a3165c99fbfe8b20a762a7a542708d1f70fd2c9","tests/ui/bad_explicit_impl.stderr":"df571e8a44b89ea0a5fab82674ebba07f3b8529b9f3365f94ab5c523859d3098","tests/ui/by_value_not_supported.rs":"9dae9d476faf4a49fadd3cc22a31269cfdf04bd875e691876232427fa27121f0","tests/ui/by_value_not_supported.stderr":"f1427b53d474842ea3c8447137f2d3ce583e5011015f7dab530ee2ae0a0e69b8","tests/ui/const_fn.rs":"2a37fb939d137c66137b8ce042f23da37cf0aa2608b8fa5577516b5afdf98918","tests/ui/const_fn.stderr":"f3449b8a20dd4b917b16324397db270326e3e5fb74e7abefa0744ffdcfe55f1b","tests/ui/data_enums.rs":"72e620d7063e6cba14c6e28ace895cccbb1b03cfc67a475da127089e2cafcfa2","tests/ui/data_enums.stderr":"bbfebf28030d6997c28f01fabb110a437924fedfa3b7830fe0da266e325dd543","tests/ui/deny_elided_lifetimes.rs":"1d94280b9219f606eafab56ba645012402ec43db7abf104ffc660cf5062de850","tests/ui/deny_elided_lifetimes.stderr":"8ce4283bd45649a31d4e1cdb644536bdc5fd9f18ad32e2cca0a727b7b39db684","tests/ui/deny_missing_docs.rs":"60f5d9aa8bab373579a2e37edb2d383ad8e451d58cad88bfde5bd2c495074427","tests/ui/deny_missing_docs.stderr":"9a578225b464ffa465b9a924c2946a6ab12e9cecce42b76cfdd1b2f80f11e3b6","tests/ui/derive_duplicate.rs":"e96bcd9d9fc0397e459fcea7116537dbadf48212840508b8d9077c050e461713","tests/ui/derive_duplicate.stderr":"9e73bc31fa7d40e0064dfc986ce871b7eff59905917b9f19d8ccb2dd5dc835b6","tests/ui/derive_noncopy.rs":"806583ff100f2195d2c57eb65b50f082736cc761bdf891a4d93f155dcfa41e8c","tests/ui/derive_noncopy.stderr":"76320c41cb9f2e23be1ce43c6dbcc84876d4f6fccc888d47eefc025d71f943ee","tests/ui/drop_shared.rs":"d79ac8893c7f2f790f0e524e8aede7b03128163f5e8ecc63e0c2b3d011684da9","tests/ui/drop_shared.stderr":"eeac8c567d4a9021e568bd401f8202c93436be6c7ca3da47089ded7097e879ec","tests/ui/empty_enum.rs":"01b3566f3ec7cabf3dc5bc48ab91f3eb177199403784fb1894bef2637bf01ae2","tests/ui/empty_enum.stderr":"095664b705f0920935f7aac560267fc29124a4cfc3fe719e4a935f0394ee17e3","tests/ui/empty_struct.rs":"d35f7a0d26e89ef59fb986698cb2f05268d2ffdb9c7493737115dfdfe9caad73","tests/ui/empty_struct.stderr":"f5515a0a0c519a54e43a3269c979e40149aab3683821af951013b13a1684dafe","tests/ui/enum_inconsistent.rs":"86a5ab50efac3791507e305f10607e5e449181f893487438411bd31dc6b01fab","tests/ui/enum_inconsistent.stderr":"384094361a936fa5a69f5ce8298d9b59eb337b1e94247db650484241e30ec308","tests/ui/enum_match_without_wildcard.rs":"1821bfcb02dee1632abe6e0466aba78b4f8957df64048bf688ccf952be042600","tests/ui/enum_match_without_wildcard.stderr":"d996a4bc687e9ff0eb96484e6329b8bbc40216819f670e5a166768144153d98b","tests/ui/enum_out_of_bounds.rs":"5efc2e3a524b7cbc8297821484c64c7b247e30cbd2ba983bca6c5d810798c8f7","tests/ui/enum_out_of_bounds.stderr":"829f0aea54f5a6bfef5792c31e189c46ef7ea3f4a921c1d755398f57f09574ff","tests/ui/enum_overflows.rs":"38b1ee3bfbeea95afcdec51436d36e9da7d10a83252d8f9072e4f5fb98808466","tests/ui/enum_overflows.stderr":"38e5f419ede3a09a70237900b4b4a0540b333843248ef6d9111d26894dfcefea","tests/ui/enum_receiver.rs":"2e21bcb006f094f9e4aaa3d2866f2b01c39b48cb449c58618e606d21571a6cf8","tests/ui/enum_receiver.stderr":"714a62232d65558525da252cb6aee24519a95abb1c1e51f855b92df22fcbd3cf","tests/ui/enum_unsatisfiable.rs":"ffb1589b9c725179d90121fb669cfde60a28f146a616d47a14876ef7612f5acf","tests/ui/enum_unsatisfiable.stderr":"fd3dac69810acedda515f9216ee728d0406f3f41c85c0872ae7bf4a8d163645b","tests/ui/expected_named.rs":"5c8b127e4c79058d72909b3c49da58251a8e4286377dc4b59bdc071bc0b6bb9d","tests/ui/expected_named.stderr":"1d7739316683bfdf1d8b5f90a2070b75078b049e25c55641eb06e9860dd51cd7","tests/ui/extern_fn_abi.rs":"78a74480fef10dca454efafd6d825d15a54ff02389ad02bcde3ead5fe21ad47a","tests/ui/extern_fn_abi.stderr":"1ee863d5039da3b95d18b020629c22c59c4f4d667c5eec31f162dc8c0c509a49","tests/ui/extern_type_bound.rs":"250c23c71f1fcf970d938510c5e068b408d88e868d0533c9d9dd755f85ee6825","tests/ui/extern_type_bound.stderr":"ada2897fa8f55e0bc81a6c44077ce97f6c8f7b6eb2db9ec912f08f0c0109d24c","tests/ui/extern_type_generic.rs":"07127a016fd008597be751a2054c1c1187b88584d9375a139afdc3a7a75a76b5","tests/ui/extern_type_generic.stderr":"f29d78dc55d685a2ffbaba4c268aab6b187539d22021f1661c2f9fb0f41d58a0","tests/ui/extern_type_lifetime_bound.rs":"8dc180b5ab5e349c06cc4a69a11fc38da35359d2bdbd3fe44d874c94595f8d76","tests/ui/extern_type_lifetime_bound.stderr":"6705be59cfd7fa143491e2cd4833ed5a5be86747b1cc205bc5daae01ffe7e5ce","tests/ui/fallible_fnptr.rs":"1f97b53efad3a45a503769390552697e4190714cf0962b2e7ef4cae34788f33f","tests/ui/fallible_fnptr.stderr":"da13f1dc56631ec5834aa7b94e760f634d188a27fccaa308b3b8fdb1de263fcf","tests/ui/function_with_body.rs":"4503b0286cdec0091270a7068da56c82d8ee2402a7c75bacbe6a362e93f798ae","tests/ui/function_with_body.stderr":"57dbdd7ecc4ca7fb8bb5ca4b29fc937a53a134e2545f13259e748b8c310b12a5","tests/ui/generic_enum.rs":"76e5f9f2879be8bb749026d2b70f4ccfe7d61c4359c6f5756080b4744af6e117","tests/ui/generic_enum.stderr":"67e3942eeefdf239b83a66201e4d9ab7bb4118ff631d2967a60cbb269e67227a","tests/ui/impl_trait_for_type.rs":"8e18904317f38db583f86bb99fe1bb05f72f355d4470720c0cc045f9c0a8af79","tests/ui/impl_trait_for_type.stderr":"90c68e040029d9dfbd95d5629b04d3461a9ab76fc671c1d2b4f71a1c2f562945","tests/ui/include.rs":"6edfd1a5884247c3bde1934e223e1944934402e9203ce66d8447ca488f5b920d","tests/ui/include.stderr":"4256f958f51da6fd738d99c28b9018bc2245218d91229e955e678f608f6365b4","tests/ui/lifetime_extern_cxx.rs":"5b529dbe92af7c9a285a26e8b6f0a1ed7d16a64c763623f6dedcdd53a5532f7f","tests/ui/lifetime_extern_cxx.stderr":"2dad200db1b083d19ce15b65058a98fb8970d9ee7ce76983fab85cc3e4009dbf","tests/ui/lifetime_extern_rust.rs":"11260b366bdedba321e12ce70a02e2212872f48bef2c47cb15ac4a8e60926158","tests/ui/lifetime_extern_rust.stderr":"79b750dcb8578e2f8c89ecc510e89c83b3e5f5e8341579c47013a7856cdb1258","tests/ui/missing_unsafe.rs":"33b099d726900590efca1396956396b0bd75d30712638a58479013037e995a32","tests/ui/missing_unsafe.stderr":"c6cc0d26cdec49dc5d185337c2b5bb2e3652c83359d33b1a69bc31e98cacc16b","tests/ui/multiple_parse_error.rs":"e34261641accec26a0bf54d7129cb6811423a2d5febf9fd4ca3136e7dea8ad8e","tests/ui/multiple_parse_error.stderr":"2fa1069b2f6206f0d21501fa6c75d0df0c5ecd300f79492285fdc4875a2457f4","tests/ui/mut_return.rs":"36f6bab6467b75796f302b537ecf72b8c7a49d2278db78b8a78dbe574549e661","tests/ui/mut_return.stderr":"ece86f33131ddc642c029287eee0ffd2af894547feb336c33e28c7385bcbc24d","tests/ui/non_integer_discriminant_enum.rs":"12fcad01a8b1fac018f0c74479f641b1f1a70c477c4854e33241e205c3fe06ce","tests/ui/non_integer_discriminant_enum.stderr":"0a300e4c4ec07e2af353756a4f6c248cd6d6dfe28a9e3e4953b8ec4f0650367a","tests/ui/nonempty_impl_block.rs":"df90794460a673f7ce3bc5b1ebabe4703a1533e671cc2727d4c1ce38fac71ca2","tests/ui/nonempty_impl_block.stderr":"b424bcedb654171786503dff51cc0451c5a387981ac8cf36b93d6a9e8d2d2959","tests/ui/nonlocal_rust_type.rs":"8c645d6ecf47f7e254609dbd61a3c444e83c577d2f5bc4bc33232b4bb537cf98","tests/ui/nonlocal_rust_type.stderr":"1ff08ffa92d7eebe25313c933cc63415acd784f552a8adf86d54c62b522922bd","tests/ui/opaque_autotraits.rs":"f35cefe65a49bf5831b3fec36d91e3bb3b81e451224950e818a8179a2c64552f","tests/ui/opaque_autotraits.stderr":"04efc0acf25bb416acbf82d5157d9e33ad186479bfa6201e91fe53c2c687cee0","tests/ui/opaque_not_sized.rs":"afa3cebdfe18c8af6ff68c428646d05256222ebe6f8c1ff98c92313007ccf478","tests/ui/opaque_not_sized.stderr":"129a27d38c46089371e6567e86f8a02838fc4e40b9a379376bb1d17cffe62e32","tests/ui/pin_mut_opaque.rs":"be170bd17d0b32e664b37f248ea7fface2a66841bf3946a30388c81e07818130","tests/ui/pin_mut_opaque.stderr":"88845d6657b7aa2f0fdbcaa41836344256f73ee0408a1553834f7616d25f8bd4","tests/ui/ptr_in_fnptr.rs":"3463ad0508b38b0c9c01e9d7950f82b31f3ce546fc1b1b2dc3f8e3f53bdb2071","tests/ui/ptr_in_fnptr.stderr":"f84e9e2fc656a63d778f9bdcb5e90b45ce4c9ef446900dc42535c3b1ef4cec95","tests/ui/ptr_missing_unsafe.rs":"10d77473002431a8f61f5745178381c701af1404c1a625cf79e4dfcd83d58eb0","tests/ui/ptr_missing_unsafe.stderr":"ff574d29f775b24ef79fd4a2b8d3db9a0d119d3fa2dfc3f21aba340c69f90812","tests/ui/ptr_no_const_mut.rs":"402cb4e26413953386975da3a3a3b7d4e35987a5297ec41713d39ae9ecdc2a0a","tests/ui/ptr_no_const_mut.stderr":"ce079cb5c0766dc8d255eabf34facaa2481545014bdbc9e1725f705e23617a68","tests/ui/ptr_unsupported.rs":"cb366f7318e70829a3ee51795e9131341352a8850381091f7b455c1cc07b98cd","tests/ui/ptr_unsupported.stderr":"04843fa471b7ceaee221339711c9cbde55bbce8457b8063cf64171b7c89f5979","tests/ui/raw_ident_namespace.rs":"0c33fda6da8426795cd7a065492c13e535d61ed645cc9510c9e6e5a5c86e454a","tests/ui/raw_ident_namespace.stderr":"7ac4ed943d8bd65f2105c09551419378c0a0dc5dcb9bb68902a79303cc33419a","tests/ui/reference_to_reference.rs":"bdefef8ca2a83244e32e2e60695e9f072af434da5330379445db62832bac703b","tests/ui/reference_to_reference.stderr":"6f52c9405b9333544237fb3c65f78b2d0db2eff234d42f4e44f65070fec3e96a","tests/ui/reserved_lifetime.rs":"58f7578fab9aff9443508c6514058ed4ea57cb78825c05e722820da233f7dbc4","tests/ui/reserved_lifetime.stderr":"0d789271dccdcc563f635bcf2a2c5c6a524db56022f5598891bd7c33a6cae062","tests/ui/reserved_name.rs":"170e31502e63a268ca7cdcffd9ca5cd25c866aff4b9be37f45e101fb9fdf3d0b","tests/ui/reserved_name.stderr":"68222eb3f3f3b36c8f78dd9999ff5474d197bb9b0cd63449233c83095571b4ed","tests/ui/result_no_display.rs":"2aeeb0769ee7daf31d2939ce8fa33692f6b031434d3698a61c0d7857d05f4162","tests/ui/result_no_display.stderr":"3c38ed3af34b17ec926b076843e9e59a81bee74accd6d927e550c988481b5cdb","tests/ui/root_namespace.rs":"32fbf454c246d6ac32c92d6735ea1ed62ad92dea5066b81e670cf7e49d8ebbeb","tests/ui/root_namespace.stderr":"23f4143ed74f7b0cce93db9199ba96732d54c220907bd06db6ce8a20d2247201","tests/ui/rust_pinned.rs":"70641aae9d6d55920ca0d698f6cda81e14545e7baa21035509d16677aff92cfa","tests/ui/rust_pinned.stderr":"9d15546013f1228c9c6aaee939f440ad523fed279f9933f8a39d3b305a873b8f","tests/ui/slice_of_type_alias.rs":"993f13727c8f07fa2c854c8751cd717db4897959af868eea774be8e4d55d5820","tests/ui/slice_of_type_alias.stderr":"a34e5f5f581b685a0a07f56ccc44f81ee559e0f4c2d6f7b7939df9684ce3d9e4","tests/ui/slice_unsupported.rs":"d8b1d2d78e53b623c53da49fb8106d1444f12daf57065b8ef230e20e0ef169b7","tests/ui/slice_unsupported.stderr":"7253a7b60d6e1565fe8f0fda20d337337439955c4a3d5ff08bb0e902f070a890","tests/ui/struct_cycle.rs":"c6cd08a87ff54b8f9bafa398dfd0f6bb254cff7b2a334ebc8297c247072727e3","tests/ui/struct_cycle.stderr":"139f25df2af2852a218ec8d702de8935e8dbfff59e2d70bcc557d419b52323e4","tests/ui/type_alias_rust.rs":"984f747141a263f6683f283e46fde771fce7a32109c70642efbec464496e5c62","tests/ui/type_alias_rust.stderr":"ca9be42c811644088880c63d095093725aab2bdafd6018f93b24288c6a3469dd","tests/ui/unique_ptr_as_mut.rs":"74408708c2c877b5fac1c8286fbcbbcc961c4a06c16a43ddfe8814a5df0e29ee","tests/ui/unique_ptr_as_mut.stderr":"383764d16c72dfd950682a49fd3940b7c2566ad1c9744e1160e3e29c41d6c981","tests/ui/unique_ptr_to_opaque.rs":"721b971ef152a946d4c1963b0f9ec1b8c74009ee76671bfb7f0873191d4942f8","tests/ui/unique_ptr_to_opaque.stderr":"230e0722acd49c45769d0dcd940c24e77aa84c0ec4e052bca90601cec8e2b261","tests/ui/unique_ptr_twice.rs":"4636f134e761490c586407d10c55adace987a3372e56933ecf62a34de0445445","tests/ui/unique_ptr_twice.stderr":"ca0ca8a3d42ce03b98165a02accf00bbe2c0d54287518e7411cd9cc3a3551fc4","tests/ui/unnamed_receiver.rs":"cf913f4d10d36925a2351a562f8f31e19564fd3eefa8254c61a7285bf17678e9","tests/ui/unnamed_receiver.stderr":"0894303e80adfd2739acd4e57116eee564034ceadef2ded756f188f423b13f7a","tests/ui/unpin_impl.rs":"8be056e6da9f4f8bdc5507614358fd480f05b8c766eb455057b25d9c90ce5685","tests/ui/unpin_impl.stderr":"e8e9f7745a840afd441154f8f51f323221407f04bb5b30607253d58da3cfa577","tests/ui/unrecognized_receiver.rs":"dbf98ad02fb1b94c08362ef805a22a69639d13cfb0442459ec1575d5d8f34131","tests/ui/unrecognized_receiver.stderr":"e89d7655d25bb7f30885a6cbf465ec48deb9cf03baa2d06b06b7a52ac3b31db7","tests/ui/unsupported_elided.rs":"fef8dc3c0157f8508465bb8dc4b1143755b1d64fb337d474cca8947545e8913d","tests/ui/unsupported_elided.stderr":"0cc81adf2755adac1c518ead46b8d1e160553b5f74fd32c8ab2c9331d0926ea1","tests/ui/vec_opaque.rs":"44ea7c5c5997614c324951bdd32a31fc98cdbfc7caaf2e422b831cdf472ad700","tests/ui/vec_opaque.stderr":"f4b28a4a5e2d08cdc7f0815c50460c83dc25f264271f6c5bea6947389df30c58","tests/ui/vector_autotraits.rs":"13b701740adf29d8158a4d47d1c1bdeac3bd32dd71107be420949122eb9b1165","tests/ui/vector_autotraits.stderr":"e40dff8a0a80516f46dae7bd3355964722d104553ca5c4afd066f7d2e2a47cf4","tests/ui/wrong_type_id.rs":"5b2519d9e4e5ccec68866e9e622e3b7c8b2d7e8845ac9f9a1fe991e595097572","tests/ui/wrong_type_id.stderr":"18c1e0fb4cca2faa4745dc3023b3f15bd179fc61b6eb3ca1074956c8c112868f","tests/unique_ptr.rs":"6ae3aa3e5a827bf119159a06f15f5f1d1ce4c7a445020f5b06152cd3d1c4ba84","tools/bazel/BUILD":"da1deb657a44d5af5e49e6044574cb05e7eabe76cc8819883494f7281143449e","tools/bazel/rust_cxx_bridge.bzl":"def942b0aaaf36439d9344172e00e40c24bf21ad6df04e7ee6e8d39ffd0f2fe6","tools/buck/buildscript.bzl":"df65723f6d21a42e9b47b26ef52e9b50105acab3196ad8b9353e8c1be5ec8cf6","tools/buck/rust_cxx_bridge.bzl":"1cc272d5b8dfe0e5c58ee9221a654ad633c8813877f51eefd8253d91af767824","tools/buck/third_party.bzl":"442f0b76f5adaf7bd15c7caf252744f89a2684d18504024256e10697c201d60b","tools/buck/toolchains/BUCK":"f422eec77dbd1d3ef10e5aa8f01000e8c0e894b7c9495ec98ee3d433d9ddbb8a","tools/cargo/build.rs":"2172af94e5b5fc49bdf75bea4639aee3825587efd964ad5b4f30fe4770ca72c0"},"package":"f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93"}
\ No newline at end of file diff --git a/vendor/cxx/BUCK b/vendor/cxx/BUCK new file mode 100644 index 000000000..f447d7291 --- /dev/null +++ b/vendor/cxx/BUCK @@ -0,0 +1,99 @@ +rust_library( + name = "cxx", + srcs = glob(["src/**/*.rs"]), + doc_deps = [ + ":cxx-build", + ], + edition = "2018", + features = [ + "alloc", + "std", + ], + visibility = ["PUBLIC"], + deps = [ + ":core", + ":cxxbridge-macro", + ], +) + +alias( + name = "codegen", + actual = ":cxxbridge", + visibility = ["PUBLIC"], +) + +rust_binary( + name = "cxxbridge", + srcs = glob(["gen/cmd/src/**/*.rs"]) + [ + "gen/cmd/src/gen", + "gen/cmd/src/syntax", + ], + edition = "2018", + deps = [ + "//third-party:clap", + "//third-party:codespan-reporting", + "//third-party:proc-macro2", + "//third-party:quote", + "//third-party:syn", + ], +) + +cxx_library( + name = "core", + srcs = ["src/cxx.cc"], + exported_headers = { + "cxx.h": "include/cxx.h", + }, + exported_linker_flags = ["-lstdc++"], + header_namespace = "rust", + visibility = ["PUBLIC"], +) + +rust_library( + name = "cxxbridge-macro", + srcs = glob(["macro/src/**/*.rs"]) + ["macro/src/syntax"], + doctests = False, + edition = "2018", + proc_macro = True, + deps = [ + "//third-party:proc-macro2", + "//third-party:quote", + "//third-party:syn", + ], +) + +rust_library( + name = "cxx-build", + srcs = glob(["gen/build/src/**/*.rs"]) + [ + "gen/build/src/gen", + "gen/build/src/syntax", + ], + doctests = False, + edition = "2018", + deps = [ + "//third-party:cc", + "//third-party:codespan-reporting", + "//third-party:once_cell", + "//third-party:proc-macro2", + "//third-party:quote", + "//third-party:scratch", + "//third-party:syn", + ], +) + +rust_library( + name = "cxx-gen", + srcs = glob(["gen/lib/src/**/*.rs"]) + [ + "gen/lib/src/gen", + "gen/lib/src/syntax", + ], + edition = "2018", + visibility = ["PUBLIC"], + deps = [ + "//third-party:cc", + "//third-party:codespan-reporting", + "//third-party:proc-macro2", + "//third-party:quote", + "//third-party:syn", + ], +) diff --git a/vendor/cxx/BUILD b/vendor/cxx/BUILD new file mode 100644 index 000000000..787994bd4 --- /dev/null +++ b/vendor/cxx/BUILD @@ -0,0 +1,93 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") +load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library", "rust_proc_macro") + +rust_library( + name = "cxx", + srcs = glob(["src/**/*.rs"]), + crate_features = [ + "alloc", + "std", + ], + edition = "2018", + proc_macro_deps = [ + ":cxxbridge-macro", + ], + visibility = ["//visibility:public"], + deps = [":core-lib"], +) + +alias( + name = "codegen", + actual = ":cxxbridge", + visibility = ["//visibility:public"], +) + +rust_binary( + name = "cxxbridge", + srcs = glob(["gen/cmd/src/**/*.rs"]), + data = ["gen/cmd/src/gen/include/cxx.h"], + edition = "2018", + deps = [ + "//third-party:clap", + "//third-party:codespan-reporting", + "//third-party:proc-macro2", + "//third-party:quote", + "//third-party:syn", + ], +) + +cc_library( + name = "core", + hdrs = ["include/cxx.h"], + include_prefix = "rust", + strip_include_prefix = "include", + visibility = ["//visibility:public"], +) + +cc_library( + name = "core-lib", + srcs = ["src/cxx.cc"], + hdrs = ["include/cxx.h"], +) + +rust_proc_macro( + name = "cxxbridge-macro", + srcs = glob(["macro/src/**/*.rs"]), + edition = "2018", + deps = [ + "//third-party:proc-macro2", + "//third-party:quote", + "//third-party:syn", + ], +) + +rust_library( + name = "cxx-build", + srcs = glob(["gen/build/src/**/*.rs"]), + data = ["gen/build/src/gen/include/cxx.h"], + edition = "2018", + deps = [ + "//third-party:cc", + "//third-party:codespan-reporting", + "//third-party:once_cell", + "//third-party:proc-macro2", + "//third-party:quote", + "//third-party:scratch", + "//third-party:syn", + ], +) + +rust_library( + name = "cxx-gen", + srcs = glob(["gen/lib/src/**/*.rs"]), + data = ["gen/lib/src/gen/include/cxx.h"], + edition = "2018", + visibility = ["//visibility:public"], + deps = [ + "//third-party:cc", + "//third-party:codespan-reporting", + "//third-party:proc-macro2", + "//third-party:quote", + "//third-party:syn", + ], +) diff --git a/vendor/cxx/Cargo.toml b/vendor/cxx/Cargo.toml new file mode 100644 index 000000000..8dd981efb --- /dev/null +++ b/vendor/cxx/Cargo.toml @@ -0,0 +1,90 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.60" +name = "cxx" +version = "1.0.94" +authors = ["David Tolnay <dtolnay@gmail.com>"] +links = "cxxbridge1" +exclude = [ + "/demo", + "/gen", + "/syntax", + "/third-party", + "/tools/buck/prelude", +] +description = "Safe interop between Rust and C++" +homepage = "https://cxx.rs" +documentation = "https://docs.rs/cxx" +readme = "README.md" +keywords = [ + "ffi", + "c++", +] +categories = [ + "development-tools::ffi", + "api-bindings", + "no-std", +] +license = "MIT OR Apache-2.0" +repository = "https://github.com/dtolnay/cxx" + +[package.metadata.docs.rs] +rustdoc-args = [ + "--cfg", + "doc_cfg", +] +targets = ["x86_64-unknown-linux-gnu"] + +[lib] +doc-scrape-examples = false + +[dependencies.cxxbridge-macro] +version = "=1.0.94" + +[dependencies.link-cplusplus] +version = "1.0" + +[dev-dependencies.cxx-build] +version = "=1.0.94" + +[dev-dependencies.cxx-gen] +version = "0.7" + +[dev-dependencies.cxx-test-suite] +version = "0" + +[dev-dependencies.rustversion] +version = "1.0" + +[dev-dependencies.trybuild] +version = "1.0.66" +features = ["diff"] + +[build-dependencies.cc] +version = "1.0.49" + +[build-dependencies.cxxbridge-flags] +version = "=1.0.94" +default-features = false + +[features] +alloc = [] +"c++14" = ["cxxbridge-flags/c++14"] +"c++17" = ["cxxbridge-flags/c++17"] +"c++20" = ["cxxbridge-flags/c++20"] +default = [ + "std", + "cxxbridge-flags/default", +] +std = ["alloc"] diff --git a/vendor/cxx/LICENSE-APACHE b/vendor/cxx/LICENSE-APACHE new file mode 100644 index 000000000..1b5ec8b78 --- /dev/null +++ b/vendor/cxx/LICENSE-APACHE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/vendor/cxx/LICENSE-MIT b/vendor/cxx/LICENSE-MIT new file mode 100644 index 000000000..31aa79387 --- /dev/null +++ b/vendor/cxx/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/vendor/cxx/README.md b/vendor/cxx/README.md new file mode 100644 index 000000000..883cfe533 --- /dev/null +++ b/vendor/cxx/README.md @@ -0,0 +1,388 @@ +CXX — safe FFI between Rust and C++ +========================================= + +[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/cxx-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/cxx) +[<img alt="crates.io" src="https://img.shields.io/crates/v/cxx.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/cxx) +[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-cxx-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/cxx) +[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/cxx/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/cxx/actions?query=branch%3Amaster) + +This library provides a **safe** mechanism for calling C++ code from Rust and +Rust code from C++, not subject to the many ways that things can go wrong when +using bindgen or cbindgen to generate unsafe C-style bindings. + +This doesn't change the fact that 100% of C++ code is unsafe. When auditing a +project, you would be on the hook for auditing all the unsafe Rust code and +*all* the C++ code. The core safety claim under this new model is that auditing +just the C++ side would be sufficient to catch all problems, i.e. the Rust side +can be 100% safe. + +```toml +[dependencies] +cxx = "1.0" + +[build-dependencies] +cxx-build = "1.0" +``` + +*Compiler support: requires rustc 1.60+ and c++11 or newer*<br> +*[Release notes](https://github.com/dtolnay/cxx/releases)* + +<br> + +## Guide + +Please see **<https://cxx.rs>** for a tutorial, reference material, and example +code. + +<br> + +## Overview + +The idea is that we define the signatures of both sides of our FFI boundary +embedded together in one Rust module (the next section shows an example). From +this, CXX receives a complete picture of the boundary to perform static analyses +against the types and function signatures to uphold both Rust's and C++'s +invariants and requirements. + +If everything checks out statically, then CXX uses a pair of code generators to +emit the relevant `extern "C"` signatures on both sides together with any +necessary static assertions for later in the build process to verify +correctness. On the Rust side this code generator is simply an attribute +procedural macro. On the C++ side it can be a small Cargo build script if your +build is managed by Cargo, or for other build systems like Bazel or Buck we +provide a command line tool which generates the header and source file and +should be easy to integrate. + +The resulting FFI bridge operates at zero or negligible overhead, i.e. no +copying, no serialization, no memory allocation, no runtime checks needed. + +The FFI signatures are able to use native types from whichever side they please, +such as Rust's `String` or C++'s `std::string`, Rust's `Box` or C++'s +`std::unique_ptr`, Rust's `Vec` or C++'s `std::vector`, etc in any combination. +CXX guarantees an ABI-compatible signature that both sides understand, based on +builtin bindings for key standard library types to expose an idiomatic API on +those types to the other language. For example when manipulating a C++ string +from Rust, its `len()` method becomes a call of the `size()` member function +defined by C++; when manipulating a Rust string from C++, its `size()` member +function calls Rust's `len()`. + +<br> + +## Example + +In this example we are writing a Rust application that wishes to take advantage +of an existing C++ client for a large-file blobstore service. The blobstore +supports a `put` operation for a discontiguous buffer upload. For example we +might be uploading snapshots of a circular buffer which would tend to consist of +2 chunks, or fragments of a file spread across memory for some other reason. + +A runnable version of this example is provided under the *demo* directory of +this repo. To try it out, run `cargo run` from that directory. + +```rust +#[cxx::bridge] +mod ffi { + // Any shared structs, whose fields will be visible to both languages. + struct BlobMetadata { + size: usize, + tags: Vec<String>, + } + + extern "Rust" { + // Zero or more opaque types which both languages can pass around but + // only Rust can see the fields. + type MultiBuf; + + // Functions implemented in Rust. + fn next_chunk(buf: &mut MultiBuf) -> &[u8]; + } + + unsafe extern "C++" { + // One or more headers with the matching C++ declarations. Our code + // generators don't read it but it gets #include'd and used in static + // assertions to ensure our picture of the FFI boundary is accurate. + include!("demo/include/blobstore.h"); + + // Zero or more opaque types which both languages can pass around but + // only C++ can see the fields. + type BlobstoreClient; + + // Functions implemented in C++. + fn new_blobstore_client() -> UniquePtr<BlobstoreClient>; + fn put(&self, parts: &mut MultiBuf) -> u64; + fn tag(&self, blobid: u64, tag: &str); + fn metadata(&self, blobid: u64) -> BlobMetadata; + } +} +``` + +Now we simply provide Rust definitions of all the things in the `extern "Rust"` +block and C++ definitions of all the things in the `extern "C++"` block, and get +to call back and forth safely. + +Here are links to the complete set of source files involved in the demo: + +- [demo/src/main.rs](demo/src/main.rs) +- [demo/build.rs](demo/build.rs) +- [demo/include/blobstore.h](demo/include/blobstore.h) +- [demo/src/blobstore.cc](demo/src/blobstore.cc) + +To look at the code generated in both languages for the example by the CXX code +generators: + +```console + # run Rust code generator and print to stdout + # (requires https://github.com/dtolnay/cargo-expand) +$ cargo expand --manifest-path demo/Cargo.toml + + # run C++ code generator and print to stdout +$ cargo run --manifest-path gen/cmd/Cargo.toml -- demo/src/main.rs +``` + +<br> + +## Details + +As seen in the example, the language of the FFI boundary involves 3 kinds of +items: + +- **Shared structs** — their fields are made visible to both languages. + The definition written within cxx::bridge is the single source of truth. + +- **Opaque types** — their fields are secret from the other language. + These cannot be passed across the FFI by value but only behind an indirection, + such as a reference `&`, a Rust `Box`, or a `UniquePtr`. Can be a type alias + for an arbitrarily complicated generic language-specific type depending on + your use case. + +- **Functions** — implemented in either language, callable from the other + language. + +Within the `extern "Rust"` part of the CXX bridge we list the types and +functions for which Rust is the source of truth. These all implicitly refer to +the `super` module, the parent module of the CXX bridge. You can think of the +two items listed in the example above as being like `use super::MultiBuf` and +`use super::next_chunk` except re-exported to C++. The parent module will either +contain the definitions directly for simple things, or contain the relevant +`use` statements to bring them into scope from elsewhere. + +Within the `extern "C++"` part, we list types and functions for which C++ is the +source of truth, as well as the header(s) that declare those APIs. In the future +it's possible that this section could be generated bindgen-style from the +headers but for now we need the signatures written out; static assertions will +verify that they are accurate. + +Your function implementations themselves, whether in C++ or Rust, *do not* need +to be defined as `extern "C"` ABI or no\_mangle. CXX will put in the right shims +where necessary to make it all work. + +<br> + +## Comparison vs bindgen and cbindgen + +Notice that with CXX there is repetition of all the function signatures: they +are typed out once where the implementation is defined (in C++ or Rust) and +again inside the cxx::bridge module, though compile-time assertions guarantee +these are kept in sync. This is different from [bindgen] and [cbindgen] where +function signatures are typed by a human once and the tool consumes them in one +language and emits them in the other language. + +[bindgen]: https://github.com/rust-lang/rust-bindgen +[cbindgen]: https://github.com/eqrion/cbindgen/ + +This is because CXX fills a somewhat different role. It is a lower level tool +than bindgen or cbindgen in a sense; you can think of it as being a replacement +for the concept of `extern "C"` signatures as we know them, rather than a +replacement for a bindgen. It would be reasonable to build a higher level +bindgen-like tool on top of CXX which consumes a C++ header and/or Rust module +(and/or IDL like Thrift) as source of truth and generates the cxx::bridge, +eliminating the repetition while leveraging the static analysis safety +guarantees of CXX. + +But note in other ways CXX is higher level than the bindgens, with rich support +for common standard library types. Frequently with bindgen when we are dealing +with an idiomatic C++ API we would end up manually wrapping that API in C-style +raw pointer functions, applying bindgen to get unsafe raw pointer Rust +functions, and replicating the API again to expose those idiomatically in Rust. +That's a much worse form of repetition because it is unsafe all the way through. + +By using a CXX bridge as the shared understanding between the languages, rather +than `extern "C"` C-style signatures as the shared understanding, common FFI use +cases become expressible using 100% safe code. + +It would also be reasonable to mix and match, using CXX bridge for the 95% of +your FFI that is straightforward and doing the remaining few oddball signatures +the old fashioned way with bindgen and cbindgen, if for some reason CXX's static +restrictions get in the way. Please file an issue if you end up taking this +approach so that we know what ways it would be worthwhile to make the tool more +expressive. + +<br> + +## Cargo-based setup + +For builds that are orchestrated by Cargo, you will use a build script that runs +CXX's C++ code generator and compiles the resulting C++ code along with any +other C++ code for your crate. + +The canonical build script is as follows. The indicated line returns a +[`cc::Build`] instance (from the usual widely used `cc` crate) on which you can +set up any additional source files and compiler flags as normal. + +[`cc::Build`]: https://docs.rs/cc/1.0/cc/struct.Build.html + +```toml +# Cargo.toml + +[build-dependencies] +cxx-build = "1.0" +``` + +```rust +// build.rs + +fn main() { + cxx_build::bridge("src/main.rs") // returns a cc::Build + .file("src/demo.cc") + .flag_if_supported("-std=c++11") + .compile("cxxbridge-demo"); + + println!("cargo:rerun-if-changed=src/main.rs"); + println!("cargo:rerun-if-changed=src/demo.cc"); + println!("cargo:rerun-if-changed=include/demo.h"); +} +``` + +<br> + +## Non-Cargo setup + +For use in non-Cargo builds like Bazel or Buck, CXX provides an alternate way of +invoking the C++ code generator as a standalone command line tool. The tool is +packaged as the `cxxbridge-cmd` crate on crates.io or can be built from the +*gen/cmd* directory of this repo. + +```bash +$ cargo install cxxbridge-cmd + +$ cxxbridge src/main.rs --header > path/to/mybridge.h +$ cxxbridge src/main.rs > path/to/mybridge.cc +``` + +<br> + +## Safety + +Be aware that the design of this library is intentionally restrictive and +opinionated! It isn't a goal to be powerful enough to handle arbitrary +signatures in either language. Instead this project is about carving out a +reasonably expressive set of functionality about which we can make useful safety +guarantees today and maybe extend over time. You may find that it takes some +practice to use CXX bridge effectively as it won't work in all the ways that you +are used to. + +Some of the considerations that go into ensuring safety are: + +- By design, our paired code generators work together to control both sides of + the FFI boundary. Ordinarily in Rust writing your own `extern "C"` blocks is + unsafe because the Rust compiler has no way to know whether the signatures + you've written actually match the signatures implemented in the other + language. With CXX we achieve that visibility and know what's on the other + side. + +- Our static analysis detects and prevents passing types by value that shouldn't + be passed by value from C++ to Rust, for example because they may contain + internal pointers that would be screwed up by Rust's move behavior. + +- To many people's surprise, it is possible to have a struct in Rust and a + struct in C++ with exactly the same layout / fields / alignment / everything, + and still not the same ABI when passed by value. This is a longstanding + bindgen bug that leads to segfaults in absolutely correct-looking code + ([rust-lang/rust-bindgen#778]). CXX knows about this and can insert the + necessary zero-cost workaround transparently where needed, so go ahead and + pass your structs by value without worries. This is made possible by owning + both sides of the boundary rather than just one. + +- Template instantiations: for example in order to expose a UniquePtr\<T\> type + in Rust backed by a real C++ unique\_ptr, we have a way of using a Rust trait + to connect the behavior back to the template instantiations performed by the + other language. + +[rust-lang/rust-bindgen#778]: https://github.com/rust-lang/rust-bindgen/issues/778 + +<br> + +## Builtin types + +In addition to all the primitive types (i32 <=> int32_t), the following +common types may be used in the fields of shared structs and the arguments and +returns of functions. + +<table> +<tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr> +<tr><td>String</td><td>rust::String</td><td></td></tr> +<tr><td>&str</td><td>rust::Str</td><td></td></tr> +<tr><td>&[T]</td><td>rust::Slice<const T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +<tr><td>&mut [T]</td><td>rust::Slice<T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +<tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr> +<tr><td>Box<T></td><td>rust::Box<T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +<tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.UniquePtr.html">UniquePtr<T></a></td><td>std::unique_ptr<T></td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr> +<tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.SharedPtr.html">SharedPtr<T></a></td><td>std::shared_ptr<T></td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr> +<tr><td>[T; N]</td><td>std::array<T, N></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +<tr><td>Vec<T></td><td>rust::Vec<T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +<tr><td><a href="https://docs.rs/cxx/1.0/cxx/struct.CxxVector.html">CxxVector<T></a></td><td>std::vector<T></td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr> +<tr><td>*mut T, *const T</td><td>T*, const T*</td><td><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr> +<tr><td>fn(T, U) -> V</td><td>rust::Fn<V(T, U)></td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr> +<tr><td>Result<T></td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr> +</table> + +The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in +this repo. You will need to include this header in your C++ code when working +with those types. + +The following types are intended to be supported "soon" but are just not +implemented yet. I don't expect any of these to be hard to make work but it's a +matter of designing a nice API for each in its non-native language. + +<table> +<tr><th>name in Rust</th><th>name in C++</th></tr> +<tr><td>BTreeMap<K, V></td><td><sup><i>tbd</i></sup></td></tr> +<tr><td>HashMap<K, V></td><td><sup><i>tbd</i></sup></td></tr> +<tr><td>Arc<T></td><td><sup><i>tbd</i></sup></td></tr> +<tr><td>Option<T></td><td><sup><i>tbd</i></sup></td></tr> +<tr><td><sup><i>tbd</i></sup></td><td>std::map<K, V></td></tr> +<tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map<K, V></td></tr> +</table> + +<br> + +## Remaining work + +This is still early days for CXX; I am releasing it as a minimum viable product +to collect feedback on the direction and invite collaborators. Please check the +open issues. + +Especially please report issues if you run into trouble building or linking any +of this stuff. I'm sure there are ways to make the build aspects friendlier or +more robust. + +Finally, I know more about Rust library design than C++ library design so I +would appreciate help making the C++ APIs in this project more idiomatic where +anyone has suggestions. + +<br> + +#### License + +<sup> +Licensed under either of <a href="LICENSE-APACHE">Apache License, Version +2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option. +</sup> + +<br> + +<sub> +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in this project by you, as defined in the Apache-2.0 license, +shall be dual licensed as above, without any additional terms or conditions. +</sub> diff --git a/vendor/cxx/WORKSPACE b/vendor/cxx/WORKSPACE new file mode 100644 index 000000000..091ad9f72 --- /dev/null +++ b/vendor/cxx/WORKSPACE @@ -0,0 +1,25 @@ +workspace(name = "cxx.rs") + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "rules_rust", + sha256 = "dc8d79fe9a5beb79d93e482eb807266a0e066e97a7b8c48d43ecf91f32a3a8f3", + urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.19.0/rules_rust-v0.19.0.tar.gz"], +) + +load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies", "rust_register_toolchains") + +rules_rust_dependencies() + +rust_register_toolchains( + versions = ["1.68.0"], +) + +load("@rules_rust//crate_universe:repositories.bzl", "crate_universe_dependencies") + +crate_universe_dependencies() + +load("//third-party/bazel:defs.bzl", "crate_repositories") + +crate_repositories() diff --git a/vendor/cxx/book/README.md b/vendor/cxx/book/README.md new file mode 100644 index 000000000..e4916e0ac --- /dev/null +++ b/vendor/cxx/book/README.md @@ -0,0 +1,9 @@ +Published automatically to https://cxx.rs from master branch. + +To build and view locally: + +- Install [mdBook]: `cargo install mdbook`. +- Run `mdbook build` in this directory. +- Open the generated *build/index.html*. + +[mdBook]: https://github.com/rust-lang/mdBook diff --git a/vendor/cxx/book/book.toml b/vendor/cxx/book/book.toml new file mode 100644 index 000000000..066f3a627 --- /dev/null +++ b/vendor/cxx/book/book.toml @@ -0,0 +1,22 @@ +[book] +#title = "Rust ♡ C++" +authors = ["David Tolnay"] +description = "CXX — safe interop between Rust and C++" + +[rust] +edition = "2018" + +[build] +build-dir = "build" +create-missing = false + +[output.html] +additional-css = ["css/cxx.css"] +cname = "cxx.rs" +git-repository-url = "https://github.com/dtolnay/cxx" +playground = { copyable = false } +print = { enable = false } + +[output.html.redirect] +"binding/index.html" = "../bindings.html" +"build/index.html" = "../building.html" diff --git a/vendor/cxx/book/build.js b/vendor/cxx/book/build.js new file mode 100755 index 000000000..2cda5860c --- /dev/null +++ b/vendor/cxx/book/build.js @@ -0,0 +1,104 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const cheerio = require('cheerio'); +const hljs = require('./build/highlight.js'); +const Entities = require('html-entities').AllHtmlEntities; +const entities = new Entities(); + +const githublink = `\ +<li class="part-title">\ +<a href="https://github.com/dtolnay/cxx">\ +<i class="fa fa-github"></i>\ +https://github.com/dtolnay/cxx\ +</a>\ +</li>`; + +const opengraph = `\ +<meta property="og:image" content="https://cxx.rs/cxx.png" />\ +<meta property="og:site_name" content="CXX" />\ +<meta property="og:title" content="CXX — safe interop between Rust and C++" />\ +<meta name="twitter:image:src" content="https://cxx.rs/cxx.png" />\ +<meta name="twitter:site" content="@davidtolnay" />\ +<meta name="twitter:card" content="summary" />\ +<meta name="twitter:title" content="CXX — safe interop between Rust and C++" />`; + +const htmljs = `\ +var html = document.querySelector('html'); +html.classList.remove('no-js'); +html.classList.add('js');`; + +const dirs = ['build']; +while (dirs.length) { + const dir = dirs.pop(); + fs.readdirSync(dir).forEach((entry) => { + path = dir + '/' + entry; + const stat = fs.statSync(path); + if (stat.isDirectory()) { + dirs.push(path); + return; + } + + if (!path.endsWith('.html')) { + return; + } + + const index = fs.readFileSync(path, 'utf8'); + const $ = cheerio.load(index, { decodeEntities: false }); + + $('head').append(opengraph); + $('script:nth-of-type(3)').text(htmljs); + $('nav#sidebar ol.chapter').append(githublink); + $('head link[href="tomorrow-night.css"]').attr('disabled', true); + $('head link[href="ayu-highlight.css"]').attr('disabled', true); + $('button#theme-toggle').attr('style', 'display:none'); + $('pre code').each(function () { + const node = $(this); + const langClass = node.attr('class').split(' ', 2)[0]; + if (!langClass.startsWith('language-')) { + return; + } + const lang = langClass.replace('language-', ''); + const lines = node.html().split('\n'); + const boring = lines.map((line) => + line.includes('<span class="boring">') + ); + const ellipsis = lines.map((line) => line.includes('// ...')); + const target = entities.decode(node.text()); + const highlighted = hljs.highlight(lang, target).value; + const result = highlighted + .split('\n') + .map(function (line, i) { + if (boring[i]) { + line = '<span class="boring">' + line; + } else if (ellipsis[i]) { + line = '<span class="ellipsis">' + line; + } + if (i > 0 && (boring[i - 1] || ellipsis[i - 1])) { + line = '</span>' + line; + } + return line; + }) + .join('\n'); + node.text(result); + node.removeClass(langClass); + if (!node.hasClass('focuscomment')) { + node.addClass('hidelines'); + node.addClass('hide-boring'); + } + }); + $('code').each(function () { + $(this).addClass('hljs'); + }); + + const out = $.html(); + fs.writeFileSync(path, out); + }); +} + +fs.copyFileSync('build/highlight.css', 'build/tomorrow-night.css'); +fs.copyFileSync('build/highlight.css', 'build/ayu-highlight.css'); + +var bookjs = fs.readFileSync('build/book.js', 'utf8'); +bookjs = bookjs.replace('set_theme(theme, false);', ''); +fs.writeFileSync('build/book.js', bookjs); diff --git a/vendor/cxx/book/build.sh b/vendor/cxx/book/build.sh new file mode 100755 index 000000000..783d304b0 --- /dev/null +++ b/vendor/cxx/book/build.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -e + +cd "$(dirname "$0")" + +if [ -f ./mdbook ]; then + ./mdbook build +else + mdbook build +fi + +if [ ! -d node_modules ]; then + npm install +fi + +./build.js diff --git a/vendor/cxx/book/css/cxx.css b/vendor/cxx/book/css/cxx.css new file mode 100644 index 000000000..647f4f716 --- /dev/null +++ b/vendor/cxx/book/css/cxx.css @@ -0,0 +1,44 @@ +:root { + --sidebar-width: 310px; +} + +.badges img { + margin: 0 7px 7px 0; +} + +.badges { + margin: 16px 0 120px; +} + +.boring { + opacity: 0.5; +} + +.no-js code:not(.focuscomment) .boring { + display: none; +} + +.js code:not(.hide-boring) .ellipsis { + display: none; +} + +.focuscomment .hljs-comment { + font-weight: bold; + color: black; +} + +.focuscomment .boring { + opacity: 0.5; +} + +nav.sidebar li.part-title i.fa-github { + font-size: 20px; + padding-right: 5px; + padding-top: 12px; + position: relative; + top: 1px; +} + +.sidebar .sidebar-scrollbox { + padding: 10px 0 10px 10px; +} diff --git a/vendor/cxx/book/diagram/Makefile b/vendor/cxx/book/diagram/Makefile new file mode 100644 index 000000000..1723a9b9f --- /dev/null +++ b/vendor/cxx/book/diagram/Makefile @@ -0,0 +1,8 @@ +overview.svg: overview.pdf + pdf2svg $< $@ + +overview.pdf: overview.tex + latexmk $< + +overview.png: overview.svg + svgexport $< $@ 3x diff --git a/vendor/cxx/book/diagram/overview.tex b/vendor/cxx/book/diagram/overview.tex new file mode 100644 index 000000000..a613bb751 --- /dev/null +++ b/vendor/cxx/book/diagram/overview.tex @@ -0,0 +1,45 @@ +\documentclass{standalone} +\usepackage{makecell} +\usepackage{pgfplots} +\usepackage{sansmath} +\usetikzlibrary{arrows.meta} +\pgfplotsset{compat=1.16} +\begin{document} +\pagecolor{white} +\begin{tikzpicture}[ + x=1cm, + y=-.6cm, + every node/.append style={ + line width=1.5pt, + font=\Large\sansmath\sffamily, + }, + every path/.append style={ + >={Latex[length=10pt,width=8pt]}, + line width=1.5pt, + }, + execute at end node={\vphantom{bg}}, +] +\node[draw, rounded corners=5, inner xsep=30pt, inner ysep=2pt] + (bridge) at (0, .25) {\makecell{\texttt{\#\hspace{-1pt}[}cxx::bridge\texttt{]} mod\\[-4pt]description of boundary}}; +\node[draw, rounded corners, inner xsep=10pt, inner ysep=6pt, text depth=1pt] + (rust-bindings) at (-3.5, 6.5) {Rust bindings}; +\node[draw, rounded corners, inner xsep=10pt, inner ysep=6pt, text depth=1pt] + (cpp-bindings) at (3.5, 6.5) {C\texttt{++} bindings}; +\node[inner xsep=4pt, inner ysep=-0pt] + (rust-code) at (-9, 6.5) {\makecell[r]{\\[-8pt]Rust\\[-4pt]code}}; +\node[inner xsep=4pt, inner ysep=-0pt] + (cpp-code) at (9, 6.5) {\makecell[l]{\\[-8pt]C\texttt{++}\\[-4pt]code}}; +\draw (bridge) -- (0, 4); +\draw[<->] (rust-bindings) |- (0, 4) -| (cpp-bindings); +\draw[<->] (rust-code) -- (rust-bindings); +\draw[<->, dash pattern=on 8pt off 6pt] (rust-bindings) -- (cpp-bindings); +\draw[<->] (cpp-bindings) -- (cpp-code); +\draw (-.75, 4) node[anchor=south east] {Macro expansion}; +\draw (.75, 4) node[anchor=south west] {Code generation}; +\draw (0, 6.5) node[anchor=south, inner ysep=4pt] {Hidden C ABI}; +\draw (-6.75, 6.5) node[anchor=south, inner ysep=1pt] {\makecell{Safe\\[-4pt]straightforward\\[-4pt]Rust APIs}}; +\draw (6.75, 6.5) node[anchor=south, inner ysep=1pt] {\makecell{Straightforward\\[-4pt]C\texttt{++} APIs}}; +\pgfresetboundingbox\path + (-9.5, 0) -- (rust-bindings.south)+(0, .3) -- (9.5, 0) -- (bridge.north); +\end{tikzpicture} +\end{document} diff --git a/vendor/cxx/book/package-lock.json b/vendor/cxx/book/package-lock.json new file mode 100644 index 000000000..dec26ad16 --- /dev/null +++ b/vendor/cxx/book/package-lock.json @@ -0,0 +1,207 @@ +{ + "name": "cxx-book-build", + "version": "0.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "cheerio": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", + "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.0", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash.assignin": "^4.0.9", + "lodash.bind": "^4.1.4", + "lodash.defaults": "^4.0.1", + "lodash.filter": "^4.4.0", + "lodash.flatten": "^4.2.0", + "lodash.foreach": "^4.3.0", + "lodash.map": "^4.4.0", + "lodash.merge": "^4.4.0", + "lodash.pick": "^4.2.1", + "lodash.reduce": "^4.4.0", + "lodash.reject": "^4.4.0", + "lodash.some": "^4.4.0" + } + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" + }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "html-entities": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", + "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==" + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "lodash.assignin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", + "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" + }, + "lodash.bind": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", + "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + }, + "lodash.filter": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", + "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + }, + "lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + }, + "lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" + }, + "lodash.reduce": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", + "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" + }, + "lodash.reject": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", + "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" + }, + "lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + } + } +} diff --git a/vendor/cxx/book/package.json b/vendor/cxx/book/package.json new file mode 100644 index 000000000..092cea218 --- /dev/null +++ b/vendor/cxx/book/package.json @@ -0,0 +1,12 @@ +{ + "name": "cxx-book-build", + "version": "0.0.0", + "main": "build.js", + "dependencies": { + "cheerio": "^0.22.0", + "html-entities": "^1.3.1" + }, + "prettier": { + "singleQuote": true + } +} diff --git a/vendor/cxx/book/src/404.md b/vendor/cxx/book/src/404.md new file mode 100644 index 000000000..c5b71f286 --- /dev/null +++ b/vendor/cxx/book/src/404.md @@ -0,0 +1,5 @@ +### Whoops, this page doesn’t exist :-( + +<br> + +<img src="https://www.rust-lang.org/static/images/ferris-error.png" alt="ferris" width="325"> diff --git a/vendor/cxx/book/src/SUMMARY.md b/vendor/cxx/book/src/SUMMARY.md new file mode 100644 index 000000000..a8f89bfc8 --- /dev/null +++ b/vendor/cxx/book/src/SUMMARY.md @@ -0,0 +1,37 @@ +# Summary + +- [Rust ❤️ C++](index.md) + +- [Core concepts](concepts.md) + +- [Tutorial](tutorial.md) + +- [Other Rust–C++ interop tools](context.md) + +- [Multi-language build system options](building.md) + - [Cargo](build/cargo.md) + - [Bazel](build/bazel.md) + - [CMake](build/cmake.md) + - [More...](build/other.md) + +- [Reference: the bridge module](reference.md) + - [extern "Rust"](extern-rust.md) + - [extern "C++"](extern-c++.md) + - [Shared types](shared.md) + - [Attributes](attributes.md) + - [Async functions](async.md) + - [Error handling](binding/result.md) + +- [Reference: built-in bindings](bindings.md) + - [String — rust::String](binding/string.md) + - [&str — rust::Str](binding/str.md) + - [&[T], &mut [T] — rust::Slice\<T\>](binding/slice.md) + - [CxxString — std::string](binding/cxxstring.md) + - [Box\<T\> — rust::Box\<T\>](binding/box.md) + - [UniquePtr\<T\> — std::unique\_ptr\<T\>](binding/uniqueptr.md) + - [SharedPtr\<T\> — std::shared\_ptr\<T\>](binding/sharedptr.md) + - [Vec\<T\> — rust::Vec\<T\>](binding/vec.md) + - [CxxVector\<T\> — std::vector\<T\>](binding/cxxvector.md) + - [*mut T, *const T raw pointers](binding/rawptr.md) + - [Function pointers](binding/fn.md) + - [Result\<T\>](binding/result.md) diff --git a/vendor/cxx/book/src/async.md b/vendor/cxx/book/src/async.md new file mode 100644 index 000000000..b4c696a36 --- /dev/null +++ b/vendor/cxx/book/src/async.md @@ -0,0 +1,86 @@ +{{#title Async functions — Rust ♡ C++}} +# Async functions + +Direct FFI of async functions is absolutely in scope for CXX (on C++20 and up) +but is not implemented yet in the current release. We are aiming for an +implementation that is as easy as: + +```rust,noplayground +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + async fn doThing(arg: Arg) -> Ret; + } +} +``` + +```cpp,hidelines +rust::Future<Ret> doThing(Arg arg) { + auto v1 = co_await f(); + auto v2 = co_await g(arg); + co_return v1 + v2; +} +``` + +## Workaround + +For now the recommended approach is to handle the return codepath over a oneshot +channel (such as [`futures::channel::oneshot`]) represented in an opaque Rust +type on the FFI. + +[`futures::channel::oneshot`]: https://docs.rs/futures/0.3.8/futures/channel/oneshot/index.html + +```rust,noplayground +// bridge.rs + +use futures::channel::oneshot; + +#[cxx::bridge] +mod ffi { + extern "Rust" { + type DoThingContext; + } + + unsafe extern "C++" { + include!("path/to/bridge_shim.h"); + + fn shim_doThing( + arg: Arg, + done: fn(Box<DoThingContext>, ret: Ret), + ctx: Box<DoThingContext>, + ); + } +} + +struct DoThingContext(oneshot::Sender<Ret>); + +pub async fn do_thing(arg: Arg) -> Ret { + let (tx, rx) = oneshot::channel(); + let context = Box::new(DoThingContext(tx)); + + ffi::shim_doThing( + arg, + |context, ret| { let _ = context.0.send(ret); }, + context, + ); + + rx.await.unwrap() +} +``` + +```cpp +// bridge_shim.cc + +#include "path/to/bridge.rs.h" +#include "rust/cxx.h" + +void shim_doThing( + Arg arg, + rust::Fn<void(rust::Box<DoThingContext> ctx, Ret ret)> done, + rust::Box<DoThingContext> ctx) noexcept { + doThing(arg) + .then([done, ctx(std::move(ctx))](auto &&res) mutable { + (*done)(std::move(ctx), std::move(res)); + }); +} +``` diff --git a/vendor/cxx/book/src/attributes.md b/vendor/cxx/book/src/attributes.md new file mode 100644 index 000000000..9c33b7771 --- /dev/null +++ b/vendor/cxx/book/src/attributes.md @@ -0,0 +1,75 @@ +{{#title Attributes — Rust ♡ C++}} +# Attributes + +## namespace + +The top-level cxx::bridge attribute macro takes an optional `namespace` argument +to control the C++ namespace into which to emit extern Rust items and the +namespace in which to expect to find the extern C++ items. + +```rust,noplayground +#[cxx::bridge(namespace = "path::of::my::company")] +mod ffi { + extern "Rust" { + type MyType; // emitted to path::of::my::company::MyType + } + + extern "C++" { + type TheirType; // refers to path::of::my::company::TheirType + } +} +``` + +Additionally, a `#[namespace = "..."]` attribute may be used inside the bridge +module on any extern block or individual item. An item will inherit the +namespace specified on its surrounding extern block if any, otherwise the +namespace specified with the top level cxx::bridge attribute if any, otherwise +the global namespace. + +```rust,noplayground +#[cxx::bridge(namespace = "third_priority")] +mod ffi { + #[namespace = "second_priority"] + extern "Rust" { + fn f(); + + #[namespace = "first_priority"] + fn g(); + } + + extern "Rust" { + fn h(); + } +} +``` + +The above would result in functions `::second_priority::f`, +`::first_priority::g`, `::third_priority::h`. + +## rust\_name, cxx\_name + +Sometimes you want the Rust name of a function or type to differ from its C++ +name. Importantly, this enables binding multiple overloads of the same C++ +function name using distinct Rust names. + +```rust,noplayground +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + #[rust_name = "i32_overloaded_function"] + fn cOverloadedFunction(x: i32) -> String; + #[rust_name = "str_overloaded_function"] + fn cOverloadedFunction(x: &str) -> String; + } +} +``` + +The `#[rust_name = "..."]` attribute replaces the name that Rust should use for +this function, and an analogous `#[cxx_name = "..."]` attribute replaces the +name that C++ should use. + +Either of the two attributes may be used on extern "Rust" as well as extern +"C++" functions, according to which one you find clearer in context. + +The same attribute works for renaming functions, opaque types, shared +structs and enums, and enum variants. diff --git a/vendor/cxx/book/src/binding/box.md b/vendor/cxx/book/src/binding/box.md new file mode 100644 index 000000000..7df195974 --- /dev/null +++ b/vendor/cxx/book/src/binding/box.md @@ -0,0 +1,120 @@ +{{#title rust::Box<T> — Rust ♡ C++}} +# rust::Box\<T\> + +### Public API: + +```cpp,hidelines +// rust/cxx.h +# +# #include <type_traits> +# +# namespace rust { + +template <typename T> +class Box final { +public: + using element_type = T; + using const_pointer = + typename std::add_pointer<typename std::add_const<T>::type>::type; + using pointer = typename std::add_pointer<T>::type; + + Box(Box &&) noexcept; + ~Box() noexcept; + + explicit Box(const T &); + explicit Box(T &&); + + Box &operator=(Box &&) noexcept; + + const T *operator->() const noexcept; + const T &operator*() const noexcept; + T *operator->() noexcept; + T &operator*() noexcept; + + template <typename... Fields> + static Box in_place(Fields &&...); + + void swap(Box &) noexcept; + + // Important: requires that `raw` came from an into_raw call. Do not + // pass a pointer from `new` or any other source. + static Box from_raw(T *) noexcept; + + T *into_raw() noexcept; +}; +# +# } // namespace rust +``` + +### Restrictions: + +Box\<T\> does not support T being an opaque C++ type. You should use +[UniquePtr\<T\>](uniqueptr.md) or [SharedPtr\<T\>](sharedptr.md) instead for +transferring ownership of opaque C++ types on the language boundary. + +If T is an opaque Rust type, the Rust type is required to be [Sized] i.e. size +known at compile time. In the future we may introduce support for dynamically +sized opaque Rust types. + +[Sized]: https://doc.rust-lang.org/std/marker/trait.Sized.html + +## Example + +This program uses a Box to pass ownership of some opaque piece of Rust state +over to C++ and then back to a Rust callback, which is a useful pattern for +implementing [async functions over FFI](../async.md). + +```rust,noplayground +// src/main.rs + +use std::io::Write; + +#[cxx::bridge] +mod ffi { + extern "Rust" { + type File; + } + + unsafe extern "C++" { + include!("example/include/example.h"); + + fn f( + callback: fn(Box<File>, fst: &str, snd: &str), + out: Box<File>, + ); + } +} + +pub struct File(std::fs::File); + +fn main() { + let out = std::fs::File::create("example.log").unwrap(); + + ffi::f( + |mut out, fst, snd| { let _ = write!(out.0, "{}{}\n", fst, snd); }, + Box::new(File(out)), + ); +} +``` + +```cpp +// include/example.h + +#pragma once +#include "example/src/main.rs.h" +#include "rust/cxx.h" + +void f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback, + rust::Box<File> out); +``` + +```cpp +// include/example.cc + +#include "example/include/example.h" + +void f(rust::Fn<void(rust::Box<File>, rust::Str, rust::Str)> callback, + rust::Box<File> out) { + callback(std::move(out), "fearless", "concurrency"); +} +``` diff --git a/vendor/cxx/book/src/binding/cxxstring.md b/vendor/cxx/book/src/binding/cxxstring.md new file mode 100644 index 000000000..cfe707f21 --- /dev/null +++ b/vendor/cxx/book/src/binding/cxxstring.md @@ -0,0 +1,140 @@ +{{#title std::string — Rust ♡ C++}} +# std::string + +The Rust binding of std::string is called **[`CxxString`]**. See the link for +documentation of the Rust API. + +[`CxxString`]: https://docs.rs/cxx/*/cxx/struct.CxxString.html + +### Restrictions: + +Rust code can never obtain a CxxString by value. C++'s string requires a move +constructor and may hold internal pointers, which is not compatible with Rust's +move behavior. Instead in Rust code we will only ever look at a CxxString +through a reference or smart pointer, as in &CxxString or Pin\<&mut CxxString\> +or UniquePtr\<CxxString\>. + +In order to construct a CxxString on the stack from Rust, you must use the +[`let_cxx_string!`] macro which will pin the string properly. The code below +uses this in one place, and the link covers the syntax. + +[`let_cxx_string!`]: https://docs.rs/cxx/*/cxx/macro.let_cxx_string.html + +## Example + +This example uses C++17's std::variant to build a toy JSON type. JSON can hold +various types including strings, and JSON's object type is a map with string +keys. The example demonstrates Rust indexing into one of those maps. + +```rust,noplayground +// src/main.rs + +use cxx::let_cxx_string; + +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + include!("example/include/json.h"); + + #[cxx_name = "json"] + type Json; + #[cxx_name = "object"] + type Object; + + fn isNull(self: &Json) -> bool; + fn isNumber(self: &Json) -> bool; + fn isString(self: &Json) -> bool; + fn isArray(self: &Json) -> bool; + fn isObject(self: &Json) -> bool; + + fn getNumber(self: &Json) -> f64; + fn getString(self: &Json) -> &CxxString; + fn getArray(self: &Json) -> &CxxVector<Json>; + fn getObject(self: &Json) -> &Object; + + #[cxx_name = "at"] + fn get<'a>(self: &'a Object, key: &CxxString) -> &'a Json; + + fn load_config() -> UniquePtr<Json>; + } +} + +fn main() { + let config = ffi::load_config(); + + let_cxx_string!(key = "name"); + println!("{}", config.getObject().get(&key).getString()); +} +``` + +```cpp +// include/json.h + +#pragma once +#include <map> +#include <memory> +#include <string> +#include <variant> +#include <vector> + +class json final { +public: + static const json null; + using number = double; + using string = std::string; + using array = std::vector<json>; + using object = std::map<string, json>; + + json() noexcept = default; + json(const json &) = default; + json(json &&) = default; + template <typename... T> + json(T &&...value) : value(std::forward<T>(value)...) {} + + bool isNull() const; + bool isNumber() const; + bool isString() const; + bool isArray() const; + bool isObject() const; + + number getNumber() const; + const string &getString() const; + const array &getArray() const; + const object &getObject() const; + +private: + std::variant<std::monostate, number, string, array, object> value; +}; + +using object = json::object; + +std::unique_ptr<json> load_config(); +``` + +```cpp +// include/json.cc + +#include "example/include/json.h" +#include <initializer_list> +#include <utility> + +const json json::null{}; +bool json::isNull() const { return std::holds_alternative<std::monostate>(value); } +bool json::isNumber() const { return std::holds_alternative<number>(value); } +bool json::isString() const { return std::holds_alternative<string>(value); } +bool json::isArray() const { return std::holds_alternative<array>(value); } +bool json::isObject() const { return std::holds_alternative<object>(value); } +json::number json::getNumber() const { return std::get<number>(value); } +const json::string &json::getString() const { return std::get<string>(value); } +const json::array &json::getArray() const { return std::get<array>(value); } +const json::object &json::getObject() const { return std::get<object>(value); } + +std::unique_ptr<json> load_config() { + return std::make_unique<json>( + std::in_place_type<json::object>, + std::initializer_list<std::pair<const std::string, json>>{ + {"name", "cxx-example"}, + {"edition", 2018.}, + {"repository", json::null}}); +} +``` diff --git a/vendor/cxx/book/src/binding/cxxvector.md b/vendor/cxx/book/src/binding/cxxvector.md new file mode 100644 index 000000000..fd95a2dbd --- /dev/null +++ b/vendor/cxx/book/src/binding/cxxvector.md @@ -0,0 +1,62 @@ +{{#title std::vector<T> — Rust ♡ C++}} +# std::vector\<T\> + +The Rust binding of std::vector\<T\> is called **[`CxxVector<T>`]**. See the +link for documentation of the Rust API. + +[`CxxVector<T>`]: https://docs.rs/cxx/*/cxx/struct.CxxVector.html + +### Restrictions: + +Rust code can never obtain a CxxVector by value. Instead in Rust code we will +only ever look at a vector behind a reference or smart pointer, as in +&CxxVector\<T\> or UniquePtr\<CxxVector\<T\>\>. + +CxxVector\<T\> does not support T being an opaque Rust type. You should use a +Vec\<T\> (C++ rust::Vec\<T\>) instead for collections of opaque Rust types on +the language boundary. + +## Example + +This program involves Rust code converting a `CxxVector<CxxString>` (i.e. +`std::vector<std::string>`) into a Rust `Vec<String>`. + +```rust,noplayground +// src/main.rs + +#![no_main] // main defined in C++ by main.cc + +use cxx::{CxxString, CxxVector}; + +#[cxx::bridge] +mod ffi { + extern "Rust" { + fn f(vec: &CxxVector<CxxString>); + } +} + +fn f(vec: &CxxVector<CxxString>) { + let vec: Vec<String> = vec + .iter() + .map(|s| s.to_string_lossy().into_owned()) + .collect(); + g(&vec); +} + +fn g(vec: &[String]) { + println!("{:?}", vec); +} +``` + +```cpp +// src/main.cc + +#include "example/src/main.rs.h" +#include <string> +#include <vector> + +int main() { + std::vector<std::string> vec{"fearless", "concurrency"}; + f(vec); +} +``` diff --git a/vendor/cxx/book/src/binding/fn.md b/vendor/cxx/book/src/binding/fn.md new file mode 100644 index 000000000..2934b0695 --- /dev/null +++ b/vendor/cxx/book/src/binding/fn.md @@ -0,0 +1,34 @@ +{{#title Function pointers — Rust ♡ C++}} +# Function pointers + +### Public API: + +```cpp,hidelines +// rust/cxx.h +# +# namespace rust { + +template <typename Signature> +class Fn; + +template <typename Ret, typename... Args> +class Fn<Ret(Args...)> final { +public: + Ret operator()(Args... args) const noexcept; + Fn operator*() const noexcept; +}; +# +# } // namespace rust +``` + +### Restrictions: + +Function pointers with a Result return type are not implemented yet. + +Passing a function pointer from C++ to Rust is not implemented yet, only from +Rust to an `extern "C++"` function is implemented. + +## Example + +Function pointers are commonly useful for implementing [async functions over +FFI](../async.md). See the example code on that page. diff --git a/vendor/cxx/book/src/binding/rawptr.md b/vendor/cxx/book/src/binding/rawptr.md new file mode 100644 index 000000000..179421127 --- /dev/null +++ b/vendor/cxx/book/src/binding/rawptr.md @@ -0,0 +1,100 @@ +{{#title *mut T, *const T — Rust ♡ C++}} +# *mut T, *const T + +Generally you should use references (`&mut T`, `&T`) or [std::unique_ptr\<T\>] +where possible over raw pointers, but raw pointers are available too as an +unsafe fallback option. + +[std::unique_ptr\<T\>]: uniqueptr.md + +### Restrictions: + +Extern functions and function pointers taking a raw pointer as an argument must +be declared `unsafe fn` i.e. unsafe to call. The same does not apply to +functions which only *return* a raw pointer, though presumably doing anything +useful with the returned pointer is going to involve unsafe code elsewhere +anyway. + +## Example + +This example illustrates making a Rust call to a canonical C-style `main` +signature involving `char *argv[]`. + +```cpp +// include/args.h + +#pragma once + +void parseArgs(int argc, char *argv[]); +``` + +```cpp +// src/args.cc + +#include "example/include/args.h" +#include <iostream> + +void parseArgs(int argc, char *argv[]) { + std::cout << argc << std::endl; + for (int i = 0; i < argc; i++) { + std::cout << '"' << argv[i] << '"' << std::endl; + } +} +``` + +```rust,noplayground +// src/main.rs + +use std::env; +use std::ffi::CString; +use std::os::raw::c_char; +use std::os::unix::ffi::OsStrExt; +use std::ptr; + +#[cxx::bridge] +mod ffi { + extern "C++" { + include!("example/include/args.h"); + + unsafe fn parseArgs(argc: i32, argv: *mut *mut c_char); + } +} + +fn main() { + // Convert from OsString to nul-terminated CString, truncating each argument + // at the first inner nul byte if present. + let args: Vec<CString> = env::args_os() + .map(|os_str| { + let bytes = os_str.as_bytes(); + CString::new(bytes).unwrap_or_else(|nul_error| { + let nul_position = nul_error.nul_position(); + let mut bytes = nul_error.into_vec(); + bytes.truncate(nul_position); + CString::new(bytes).unwrap() + }) + }) + .collect(); + + // Convert from Vec<CString> of owned strings to Vec<*mut c_char> of + // borrowed string pointers. + // + // Once extern type stabilizes (https://github.com/rust-lang/rust/issues/43467) + // and https://internals.rust-lang.org/t/pre-rfc-make-cstr-a-thin-pointer/6258 + // is implemented, and CStr pointers become thin, we can sidestep this step + // by accumulating the args as Vec<Box<CStr>> up front, then simply casting + // from *mut [Box<CStr>] to *mut [*mut CStr] to *mut *mut c_char. + let argc = args.len(); + let mut argv: Vec<*mut c_char> = Vec::with_capacity(argc + 1); + for arg in &args { + argv.push(arg.as_ptr() as *mut c_char); + } + argv.push(ptr::null_mut()); // Nul terminator. + + unsafe { + ffi::parseArgs(argc as i32, argv.as_mut_ptr()); + } + + // The CStrings go out of scope here. C function must not have held on to + // the pointers beyond this point. +} +``` diff --git a/vendor/cxx/book/src/binding/result.md b/vendor/cxx/book/src/binding/result.md new file mode 100644 index 000000000..e49dcf4de --- /dev/null +++ b/vendor/cxx/book/src/binding/result.md @@ -0,0 +1,148 @@ +{{#title Result<T> — Rust ♡ C++}} +# Result\<T\> + +Result\<T\> is allowed as the return type of an extern function in either +direction. Its behavior is to translate to/from C++ exceptions. If your codebase +does not use C++ exceptions, or prefers to represent fallibility using something +like outcome\<T\>, leaf::result\<T\>, StatusOr\<T\>, etc then you'll need to +handle the translation of those to Rust Result\<T\> using your own shims for +now. Better support for this is planned. + +If an exception is thrown from an `extern "C++"` function that is *not* declared +by the CXX bridge to return Result, the program calls C++'s `std::terminate`. +The behavior is equivalent to the same exception being thrown through a +`noexcept` C++ function. + +If a panic occurs in *any* `extern "Rust"` function, regardless of whether it is +declared by the CXX bridge to return Result, a message is logged and the program +calls Rust's `std::process::abort`. + +## Returning Result from Rust to C++ + +An `extern "Rust"` function returning a Result turns into a `throw` in C++ if +the Rust side produces an error. + +Note that the return type written inside of cxx::bridge must be written without +a second type parameter. Only the Ok type is specified for the purpose of the +FFI. The Rust *implementation* (outside of the bridge module) may pick any error +type as long as it has a std::fmt::Display impl. + +```rust,noplayground +# use std::io; +# +#[cxx::bridge] +mod ffi { + extern "Rust" { + fn fallible1(depth: usize) -> Result<String>; + fn fallible2() -> Result<()>; + } +} + +fn fallible1(depth: usize) -> anyhow::Result<String> { + if depth == 0 { + return Err(anyhow::Error::msg("fallible1 requires depth > 0")); + } + ... +} + +fn fallible2() -> Result<(), io::Error> { + ... + Ok(()) +} +``` + +The exception that gets thrown by CXX on the C++ side is always of type +`rust::Error` and has the following C++ public API. The `what()` member function +gives the error message according to the Rust error's std::fmt::Display impl. + +```cpp,hidelines +// rust/cxx.h +# +# namespace rust { + +class Error final : public std::exception { +public: + Error(const Error &); + Error(Error &&) noexcept; + ~Error() noexcept; + + Error &operator=(const Error &); + Error &operator=(Error &&) noexcept; + + const char *what() const noexcept override; +}; +# +# } // namespace rust +``` + +## Returning Result from C++ to Rust + +An `extern "C++"` function returning a Result turns into a `catch` in C++ that +converts the exception into an Err for Rust. + +Note that the return type written inside of cxx::bridge must be written without +a second type parameter. Only the Ok type is specified for the purpose of the +FFI. The resulting error type created by CXX when an `extern "C++"` function +throws will always be of type **[`cxx::Exception`]**. + +[`cxx::Exception`]: https://docs.rs/cxx/*/cxx/struct.Exception.html + +```rust,noplayground +# use std::process; +# +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + include!("example/include/example.h"); + fn fallible1(depth: usize) -> Result<String>; + fn fallible2() -> Result<()>; + } +} + +fn main() { + if let Err(err) = ffi::fallible1(99) { + eprintln!("Error: {}", err); + process::exit(1); + } +} +``` + +The specific set of caught exceptions and the conversion to error message are +both customizable. The way you do this is by defining a template function +`rust::behavior::trycatch` with a suitable signature inside any one of the +headers `include!`'d by your cxx::bridge. + +The template signature is required to be: + +```cpp,hidelines +namespace rust { +namespace behavior { + +template <typename Try, typename Fail> +static void trycatch(Try &&func, Fail &&fail) noexcept; + +} // namespace behavior +} // namespace rust +``` + +The default `trycatch` used by CXX if you have not provided your own is the +following. You must follow the same pattern: invoke `func` with no arguments, +catch whatever exception(s) you want, and invoke `fail` with the error message +you'd like for the Rust error to have. + +```cpp,hidelines +# #include <exception> +# +# namespace rust { +# namespace behavior { +# +template <typename Try, typename Fail> +static void trycatch(Try &&func, Fail &&fail) noexcept try { + func(); +} catch (const std::exception &e) { + fail(e.what()); +} +# +# } // namespace behavior +# } // namespace rust +``` diff --git a/vendor/cxx/book/src/binding/sharedptr.md b/vendor/cxx/book/src/binding/sharedptr.md new file mode 100644 index 000000000..a3b707008 --- /dev/null +++ b/vendor/cxx/book/src/binding/sharedptr.md @@ -0,0 +1,80 @@ +{{#title std::shared_ptr<T> — Rust ♡ C++}} +# std::shared\_ptr\<T\> + +The Rust binding of std::shared\_ptr\<T\> is called **[`SharedPtr<T>`]**. See +the link for documentation of the Rust API. + +[`SharedPtr<T>`]: https://docs.rs/cxx/*/cxx/struct.SharedPtr.html + +### Restrictions: + +SharedPtr\<T\> does not support T being an opaque Rust type. You should use a +Box\<T\> (C++ [rust::Box\<T\>](box.md)) instead for transferring ownership of +opaque Rust types on the language boundary. + +## Example + +```rust,noplayground +// src/main.rs + +use std::ops::Deref; +use std::ptr; + +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + include!("example/include/example.h"); + + type Object; + + fn create_shared_ptr() -> SharedPtr<Object>; + } +} + +fn main() { + let ptr1 = ffi::create_shared_ptr(); + + { + // Create a second shared_ptr holding shared ownership of the same + // object. There is still only one Object but two SharedPtr<Object>. + // Both pointers point to the same object on the heap. + let ptr2 = ptr1.clone(); + assert!(ptr::eq(ptr1.deref(), ptr2.deref())); + + // ptr2 goes out of scope, but Object is not destroyed yet. + } + + println!("say goodbye to Object"); + + // ptr1 goes out of scope and Object is destroyed. +} +``` + +```cpp +// include/example.h + +#pragma once +#include <memory> + +class Object { +public: + Object(); + ~Object(); +}; + +std::shared_ptr<Object> create_shared_ptr(); +``` + +```cpp +// src/example.cc + +#include "example/include/example.h" +#include <iostream> + +Object::Object() { std::cout << "construct Object" << std::endl; } +Object::~Object() { std::cout << "~Object" << std::endl; } + +std::shared_ptr<Object> create_shared_ptr() { + return std::make_shared<Object>(); +} +``` diff --git a/vendor/cxx/book/src/binding/slice.md b/vendor/cxx/book/src/binding/slice.md new file mode 100644 index 000000000..803277ba9 --- /dev/null +++ b/vendor/cxx/book/src/binding/slice.md @@ -0,0 +1,171 @@ +{{#title rust::Slice<T> — Rust ♡ C++}} +# rust::Slice\<const T\>, rust::Slice\<T\> + +- Rust `&[T]` is written `rust::Slice<const T>` in C++ +- Rust `&mut [T]` is written `rust::Slice<T>` in C++ + +### Public API: + +```cpp,hidelines +// rust/cxx.h +# +# #include <iterator> +# #include <type_traits> +# +# namespace rust { + +template <typename T> +class Slice final { +public: + using value_type = T; + + Slice() noexcept; + Slice(const Slice<T> &) noexcept; + Slice(T *, size_t count) noexcept; + + Slice &operator=(Slice<T> &&) noexcept; + Slice &operator=(const Slice<T> &) noexcept + requires std::is_const_v<T>; + + T *data() const noexcept; + size_t size() const noexcept; + size_t length() const noexcept; + bool empty() const noexcept; + + T &operator[](size_t n) const noexcept; + T &at(size_t n) const; + T &front() const noexcept; + T &back() const noexcept; + + class iterator; + iterator begin() const noexcept; + iterator end() const noexcept; + + void swap(Slice &) noexcept; +}; +# +# template <typename T> +# class Slice<T>::iterator final { +# public: +# using iterator_category = std::random_access_iterator_tag; +# using value_type = T; +# using pointer = T *; +# using reference = T &; +# +# T &operator*() const noexcept; +# T *operator->() const noexcept; +# T &operator[](ptrdiff_t) const noexcept; +# +# iterator &operator++() noexcept; +# iterator operator++(int) noexcept; +# iterator &operator--() noexcept; +# iterator operator--(int) noexcept; +# +# iterator &operator+=(ptrdiff_t) noexcept; +# iterator &operator-=(ptrdiff_t) noexcept; +# iterator operator+(ptrdiff_t) const noexcept; +# iterator operator-(ptrdiff_t) const noexcept; +# ptrdiff_t operator-(const iterator &) const noexcept; +# +# bool operator==(const iterator &) const noexcept; +# bool operator!=(const iterator &) const noexcept; +# bool operator<(const iterator &) const noexcept; +# bool operator>(const iterator &) const noexcept; +# bool operator<=(const iterator &) const noexcept; +# bool operator>=(const iterator &) const noexcept; +# }; +# +# } // namespace rust +``` + +### Restrictions: + +T must not be an opaque Rust type or opaque C++ type. Support for opaque Rust +types in slices is coming. + +Allowed as function argument or return value. Not supported in shared structs. + +Only rust::Slice\<const T\> is copy-assignable, not rust::Slice\<T\>. (Both are +move-assignable.) You'll need to write std::move occasionally as a reminder that +accidentally exposing overlapping &mut \[T\] to Rust is UB. + +## Example + +This example is a C++ program that constructs a slice containing JSON data (by +reading from stdin, but it could be from anywhere), then calls into Rust to +pretty-print that JSON data into a std::string via the [serde_json] and +[serde_transcode] crates. + +[serde_json]: https://github.com/serde-rs/json +[serde_transcode]: https://github.com/sfackler/serde-transcode + +```rust,noplayground +// src/main.rs + +#![no_main] // main defined in C++ by main.cc + +use cxx::CxxString; +use std::io::{self, Write}; +use std::pin::Pin; + +#[cxx::bridge] +mod ffi { + extern "Rust" { + fn prettify_json(input: &[u8], output: Pin<&mut CxxString>) -> Result<()>; + } +} + +struct WriteToCxxString<'a>(Pin<&'a mut CxxString>); + +impl<'a> Write for WriteToCxxString<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.0.as_mut().push_bytes(buf); + Ok(buf.len()) + } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +fn prettify_json(input: &[u8], output: Pin<&mut CxxString>) -> serde_json::Result<()> { + let writer = WriteToCxxString(output); + let mut deserializer = serde_json::Deserializer::from_slice(input); + let mut serializer = serde_json::Serializer::pretty(writer); + serde_transcode::transcode(&mut deserializer, &mut serializer) +} +``` + +```cpp +// src/main.cc + +#include "example/src/main.rs.h" +#include <iostream> +#include <iterator> +#include <string> +#include <vector> + +int main() { + // Read json from stdin. + std::istreambuf_iterator<char> begin{std::cin}, end; + std::vector<unsigned char> input{begin, end}; + rust::Slice<const uint8_t> slice{input.data(), input.size()}; + + // Prettify using serde_json and serde_transcode. + std::string output; + prettify_json(slice, output); + + // Write to stdout. + std::cout << output << std::endl; +} +``` + +Testing the example: + +```console +$ echo '{"fearless":"concurrency"}' | cargo run + Finished dev [unoptimized + debuginfo] target(s) in 0.02s + Running `target/debug/example` +{ + "fearless": "concurrency" +} +``` diff --git a/vendor/cxx/book/src/binding/str.md b/vendor/cxx/book/src/binding/str.md new file mode 100644 index 000000000..9c1e0a773 --- /dev/null +++ b/vendor/cxx/book/src/binding/str.md @@ -0,0 +1,118 @@ +{{#title rust::Str — Rust ♡ C++}} +# rust::Str + +### Public API: + +```cpp,hidelines +// rust/cxx.h +# +# #include <iosfwd> +# #include <string> +# +# namespace rust { + +class Str final { +public: + Str() noexcept; + Str(const Str &) noexcept; + Str(const String &) noexcept; + + // Throws std::invalid_argument if not utf-8. + Str(const std::string &); + Str(const char *); + Str(const char *, size_t); + + Str &operator=(const Str &) noexcept; + + explicit operator std::string() const; + + // Note: no null terminator. + const char *data() const noexcept; + size_t size() const noexcept; + size_t length() const noexcept; + bool empty() const noexcept; + + using iterator = const char *; + using const_iterator = const char *; + const_iterator begin() const noexcept; + const_iterator end() const noexcept; + const_iterator cbegin() const noexcept; + const_iterator cend() const noexcept; + + bool operator==(const Str &) const noexcept; + bool operator!=(const Str &) const noexcept; + bool operator<(const Str &) const noexcept; + bool operator<=(const Str &) const noexcept; + bool operator>(const Str &) const noexcept; + bool operator>=(const Str &) const noexcept; + + void swap(Str &) noexcept; +}; + +std::ostream &operator<<(std::ostream &, const Str &); +# +# } // namespace rust +``` + +### Notes: + +**Be aware that rust::Str behaves like &str i.e. it is a borrow!** C++ +needs to be mindful of the lifetimes at play. + +Just to reiterate: &str is rust::Str. Do not try to write &str as `const +rust::Str &`. A language-level C++ reference is not able to capture the fat +pointer nature of &str. + +### Restrictions: + +Allowed as function argument or return value. Not supported in shared structs +yet. `&mut str` is not supported yet, but is also extremely obscure so this is +fine. + +## Example + +```rust,noplayground +// src/main.rs + +#[cxx::bridge] +mod ffi { + extern "Rust" { + fn r(greeting: &str); + } + + unsafe extern "C++" { + include!("example/include/greeting.h"); + fn c(greeting: &str); + } +} + +fn r(greeting: &str) { + println!("{}", greeting); +} + +fn main() { + ffi::c("hello from Rust"); +} +``` + +```cpp +// include/greeting.h + +#pragma once +#include "example/src/main.rs.h" +#include "rust/cxx.h" + +void c(rust::Str greeting); +``` + +```cpp +// src/greeting.cc + +#include "example/include/greeting.h" +#include <iostream> + +void c(rust::Str greeting) { + std::cout << greeting << std::endl; + r("hello from C++"); +} +``` diff --git a/vendor/cxx/book/src/binding/string.md b/vendor/cxx/book/src/binding/string.md new file mode 100644 index 000000000..1e4827812 --- /dev/null +++ b/vendor/cxx/book/src/binding/string.md @@ -0,0 +1,132 @@ +{{#title rust::String — Rust ♡ C++}} +# rust::String + +### Public API: + +```cpp,hidelines +// rust/cxx.h +# +# #include <iosfwd> +# #include <string> +# +# namespace rust { + +class String final { +public: + String() noexcept; + String(const String &) noexcept; + String(String &&) noexcept; + ~String() noexcept; + + // Throws std::invalid_argument if not UTF-8. + String(const std::string &); + String(const char *); + String(const char *, size_t); + + // Replaces invalid UTF-8 data with the replacement character (U+FFFD). + static String lossy(const std::string &) noexcept; + static String lossy(const char *) noexcept; + static String lossy(const char *, size_t) noexcept; + + // Throws std::invalid_argument if not UTF-16. + String(const char16_t *); + String(const char16_t *, size_t); + + // Replaces invalid UTF-16 data with the replacement character (U+FFFD). + static String lossy(const char16_t *) noexcept; + static String lossy(const char16_t *, size_t) noexcept; + + String &operator=(const String &) noexcept; + String &operator=(String &&) noexcept; + + explicit operator std::string() const; + + // Note: no null terminator. + const char *data() const noexcept; + size_t size() const noexcept; + size_t length() const noexcept; + bool empty() const noexcept; + + const char *c_str() noexcept; + + size_t capacity() const noexcept; + void reserve(size_t new_cap) noexcept; + + using iterator = char *; + iterator begin() noexcept; + iterator end() noexcept; + + using const_iterator = const char *; + const_iterator begin() const noexcept; + const_iterator end() const noexcept; + const_iterator cbegin() const noexcept; + const_iterator cend() const noexcept; + + bool operator==(const String &) const noexcept; + bool operator!=(const String &) const noexcept; + bool operator<(const String &) const noexcept; + bool operator<=(const String &) const noexcept; + bool operator>(const String &) const noexcept; + bool operator>=(const String &) const noexcept; + + void swap(String &) noexcept; +}; + +std::ostream &operator<<(std::ostream &, const String &); +# +# } // namespace rust +``` + +### Restrictions: + +None. Strings may be used as function arguments and function return values, by +value or by reference, as well as fields of shared structs. + +## Example + +```rust,noplayground +// src/main.rs + +#[cxx::bridge] +mod ffi { + struct ConcatRequest { + fst: String, + snd: String, + } + + unsafe extern "C++" { + include!("example/include/concat.h"); + fn concat(r: ConcatRequest) -> String; + } +} + +fn main() { + let concatenated = ffi::concat(ffi::ConcatRequest { + fst: "fearless".to_owned(), + snd: "concurrency".to_owned(), + }); + println!("concatenated: {:?}", concatenated); +} +``` + +```cpp +// include/concat.h + +#pragma once +#include "example/src/main.rs.h" +#include "rust/cxx.h" + +rust::String concat(ConcatRequest r); +``` + +```cpp +// src/concat.cc + +#include "example/include/concat.h" + +rust::String concat(ConcatRequest r) { + // The full suite of operator overloads hasn't been added + // yet on rust::String, but we can get it done like this: + return std::string(r.fst) + std::string(r.snd); +} +``` diff --git a/vendor/cxx/book/src/binding/uniqueptr.md b/vendor/cxx/book/src/binding/uniqueptr.md new file mode 100644 index 000000000..eefbc34a3 --- /dev/null +++ b/vendor/cxx/book/src/binding/uniqueptr.md @@ -0,0 +1,63 @@ +{{#title std::unique_ptr<T> — Rust ♡ C++}} +# std::unique\_ptr\<T\> + +The Rust binding of std::unique\_ptr\<T\> is called **[`UniquePtr<T>`]**. See +the link for documentation of the Rust API. + +[`UniquePtr<T>`]: https://docs.rs/cxx/*/cxx/struct.UniquePtr.html + +### Restrictions: + +Only `std::unique_ptr<T, std::default_delete<T>>` is currently supported. Custom +deleters may be supported in the future. + +UniquePtr\<T\> does not support T being an opaque Rust type. You should use a +Box\<T\> (C++ [rust::Box\<T\>](box.md)) instead for transferring ownership of +opaque Rust types on the language boundary. + +## Example + +UniquePtr is commonly useful for returning opaque C++ objects to Rust. This use +case was featured in the [*blobstore tutorial*](../tutorial.md). + +```rust,noplayground +// src/main.rs + +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + include!("example/include/blobstore.h"); + + type BlobstoreClient; + + fn new_blobstore_client() -> UniquePtr<BlobstoreClient>; + // ... + } +} + +fn main() { + let client = ffi::new_blobstore_client(); + // ... +} +``` + +```cpp +// include/blobstore.h + +#pragma once +#include <memory> + +class BlobstoreClient; + +std::unique_ptr<BlobstoreClient> new_blobstore_client(); +``` + +```cpp +// src/blobstore.cc + +#include "example/include/blobstore.h" + +std::unique_ptr<BlobstoreClient> new_blobstore_client() { + return std::make_unique<BlobstoreClient>(); +} +``` diff --git a/vendor/cxx/book/src/binding/vec.md b/vendor/cxx/book/src/binding/vec.md new file mode 100644 index 000000000..4d6587ab1 --- /dev/null +++ b/vendor/cxx/book/src/binding/vec.md @@ -0,0 +1,192 @@ +{{#title rust::Vec<T> — Rust ♡ C++}} +# rust::Vec\<T\> + +### Public API: + +```cpp,hidelines +// rust/cxx.h +# +# #include <initializer_list> +# #include <iterator> +# #include <type_traits> +# +# namespace rust { + +template <typename T> +class Vec final { +public: + using value_type = T; + + Vec() noexcept; + Vec(std::initializer_list<T>); + Vec(const Vec &); + Vec(Vec &&) noexcept; + ~Vec() noexcept; + + Vec &operator=(Vec &&) noexcept; + Vec &operator=(const Vec &); + + size_t size() const noexcept; + bool empty() const noexcept; + const T *data() const noexcept; + T *data() noexcept; + size_t capacity() const noexcept; + + const T &operator[](size_t n) const noexcept; + const T &at(size_t n) const; + const T &front() const; + const T &back() const; + + T &operator[](size_t n) noexcept; + T &at(size_t n); + T &front(); + T &back(); + + void reserve(size_t new_cap); + void push_back(const T &value); + void push_back(T &&value); + template <typename... Args> + void emplace_back(Args &&...args); + void truncate(size_t len); + void clear(); + + class iterator; + iterator begin() noexcept; + iterator end() noexcept; + + class const_iterator; + const_iterator begin() const noexcept; + const_iterator end() const noexcept; + const_iterator cbegin() const noexcept; + const_iterator cend() const noexcept; + + void swap(Vec &) noexcept; +}; +# +# template <typename T> +# class Vec<T>::iterator final { +# public: +# using iterator_category = std::random_access_iterator_tag; +# using value_type = T; +# using pointer = T *; +# using reference = T &; +# +# T &operator*() const noexcept; +# T *operator->() const noexcept; +# T &operator[](ptrdiff_t) const noexcept; +# +# iterator &operator++() noexcept; +# iterator operator++(int) noexcept; +# iterator &operator--() noexcept; +# iterator operator--(int) noexcept; +# +# iterator &operator+=(ptrdiff_t) noexcept; +# iterator &operator-=(ptrdiff_t) noexcept; +# iterator operator+(ptrdiff_t) const noexcept; +# iterator operator-(ptrdiff_t) const noexcept; +# ptrdiff_t operator-(const iterator &) const noexcept; +# +# bool operator==(const iterator &) const noexcept; +# bool operator!=(const iterator &) const noexcept; +# bool operator<(const iterator &) const noexcept; +# bool operator<=(const iterator &) const noexcept; +# bool operator>(const iterator &) const noexcept; +# bool operator>=(const iterator &) const noexcept; +# }; +# +# template <typename T> +# class Vec<T>::const_iterator final { +# public: +# using iterator_category = std::random_access_iterator_tag; +# using value_type = const T; +# using pointer = const T *; +# using reference = const T &; +# +# const T &operator*() const noexcept; +# const T *operator->() const noexcept; +# const T &operator[](ptrdiff_t) const noexcept; +# +# const_iterator &operator++() noexcept; +# const_iterator operator++(int) noexcept; +# const_iterator &operator--() noexcept; +# const_iterator operator--(int) noexcept; +# +# const_iterator &operator+=(ptrdiff_t) noexcept; +# const_iterator &operator-=(ptrdiff_t) noexcept; +# const_iterator operator+(ptrdiff_t) const noexcept; +# const_iterator operator-(ptrdiff_t) const noexcept; +# ptrdiff_t operator-(const const_iterator &) const noexcept; +# +# bool operator==(const const_iterator &) const noexcept; +# bool operator!=(const const_iterator &) const noexcept; +# bool operator<(const const_iterator &) const noexcept; +# bool operator<=(const const_iterator &) const noexcept; +# bool operator>(const const_iterator &) const noexcept; +# bool operator>=(const const_iterator &) const noexcept; +# }; +# +# } // namespace rust +``` + +### Restrictions: + +Vec\<T\> does not support T being an opaque C++ type. You should use +CxxVector\<T\> (C++ std::vector\<T\>) instead for collections of opaque C++ +types on the language boundary. + +## Example + +```rust,noplayground +// src/main.rs + +#[cxx::bridge] +mod ffi { + struct Shared { + v: u32, + } + + unsafe extern "C++" { + include!("example/include/example.h"); + + fn f(elements: Vec<Shared>); + } +} + +fn main() { + let shared = |v| ffi::Shared { v }; + let elements = vec![shared(3), shared(2), shared(1)]; + ffi::f(elements); +} +``` + +```cpp +// include/example.h + +#pragma once +#include "example/src/main.rs.h" +#include "rust/cxx.h" + +void f(rust::Vec<Shared> elements); +``` + +```cpp +// src/example.cc + +#include "example/include/example.h" +#include <algorithm> +#include <cassert> +#include <iostream> +#include <iterator> +#include <vector> + +void f(rust::Vec<Shared> v) { + for (auto shared : v) { + std::cout << shared.v << std::endl; + } + + // Copy the elements to a C++ std::vector using STL algorithm. + std::vector<Shared> stdv; + std::copy(v.begin(), v.end(), std::back_inserter(stdv)); + assert(v.size() == stdv.size()); +} +``` diff --git a/vendor/cxx/book/src/bindings.md b/vendor/cxx/book/src/bindings.md new file mode 100644 index 000000000..bcb51d8e0 --- /dev/null +++ b/vendor/cxx/book/src/bindings.md @@ -0,0 +1,56 @@ +{{#title Built-in bindings — Rust ♡ C++}} +# Built-in bindings reference + +In addition to all the primitive types (i32 <=> int32_t), the following +common types may be used in the fields of shared structs and the arguments and +returns of extern functions. + +<br> + +<table> +<tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr> +<tr><td style="padding:3px 6px">String</td><td style="padding:3px 6px"><b><a href="binding/string.md">rust::String</a></b></td><td style="padding:3px 6px"></td></tr> +<tr><td style="padding:3px 6px">&str</td><td style="padding:3px 6px"><b><a href="binding/str.md">rust::Str</a></b></td><td style="padding:3px 6px"></td></tr> +<tr><td style="padding:3px 6px">&[T]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice<const T></a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +<tr><td style="padding:3px 6px">&mut [T]</td><td style="padding:3px 6px"><b><a href="binding/slice.md">rust::Slice<T></a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +<tr><td style="padding:3px 6px"><b><a href="binding/cxxstring.md">CxxString</a></b></td><td style="padding:3px 6px">std::string</td><td style="padding:3px 6px"><sup><i>cannot be passed by value</i></sup></td></tr> +<tr><td style="padding:3px 6px">Box<T></td><td style="padding:3px 6px"><b><a href="binding/box.md">rust::Box<T></a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +<tr><td style="padding:3px 6px"><b><a href="binding/uniqueptr.md">UniquePtr<T></a></b></td><td style="padding:3px 6px">std::unique_ptr<T></td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr> +<tr><td style="padding:3px 6px"><b><a href="binding/sharedptr.md">SharedPtr<T></a></b></td><td style="padding:3px 6px">std::shared_ptr<T></td><td style="padding:3px 6px"><sup><i>cannot hold opaque Rust type</i></sup></td></tr> +<tr><td style="padding:3px 6px">[T; N]</td><td style="padding:3px 6px">std::array<T, N></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +<tr><td style="padding:3px 6px">Vec<T></td><td style="padding:3px 6px"><b><a href="binding/vec.md">rust::Vec<T></a></b></td><td style="padding:3px 6px"><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +<tr><td style="padding:3px 6px"><b><a href="binding/cxxvector.md">CxxVector<T></a></b></td><td style="padding:3px 6px">std::vector<T></td><td style="padding:3px 6px"><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr> +<tr><td style="padding:3px 6px"><b><a href="binding/rawptr.md">*mut T, *const T</a></b></td><td style="padding:3px 6px">T*, const T*</td><td style="padding:3px 6px"><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr> +<tr><td style="padding:3px 6px">fn(T, U) -> V</td><td style="padding:3px 6px"><b><a href="binding/fn.md">rust::Fn<V(T, U)></a></b></td><td style="padding:3px 6px"><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr> +<tr><td style="padding:3px 6px"><b><a href="binding/result.md">Result<T></a></b></td><td style="padding:3px 6px">throw/catch</td><td style="padding:3px 6px"><sup><i>allowed as return type only</i></sup></td></tr> +</table> + +<br> + +The C++ API of the `rust` namespace is defined by the *include/cxx.h* file in +the CXX GitHub repo. You will need to include this header in your C++ code when +working with those types. **When using Cargo and the cxx-build crate, the header +is made available to you at `#include "rust/cxx.h"`.** + +The `rust` namespace additionally provides lowercase type aliases of all the +types mentioned in the table, for use in codebases preferring that style. For +example `rust::String`, `rust::Vec` may alternatively be written `rust::string`, +`rust::vec` etc. + +## Pending bindings + +The following types are intended to be supported "soon" but are just not +implemented yet. I don't expect any of these to be hard to make work but it's a +matter of designing a nice API for each in its non-native language. + +<br> + +<table> +<tr><th>name in Rust</th><th>name in C++</th></tr> +<tr><td>BTreeMap<K, V></td><td><sup><i>tbd</i></sup></td></tr> +<tr><td>HashMap<K, V></td><td><sup><i>tbd</i></sup></td></tr> +<tr><td>Arc<T></td><td><sup><i>tbd</i></sup></td></tr> +<tr><td>Option<T></td><td><sup><i>tbd</i></sup></td></tr> +<tr><td><sup><i>tbd</i></sup></td><td>std::map<K, V></td></tr> +<tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map<K, V></td></tr> +</table> diff --git a/vendor/cxx/book/src/build/bazel.md b/vendor/cxx/book/src/build/bazel.md new file mode 100644 index 000000000..6a2c82b00 --- /dev/null +++ b/vendor/cxx/book/src/build/bazel.md @@ -0,0 +1,106 @@ +{{#title Bazel, Buck — Rust ♡ C++}} +## Bazel, Buck, potentially other similar environments + +Starlark-based build systems with the ability to compile a code generator and +invoke it as a `genrule` will run CXX's C++ code generator via its `cxxbridge` +command line interface. + +The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be built +from the *gen/cmd/* directory of the CXX GitHub repo. + +```console +$ cargo install cxxbridge-cmd + +$ cxxbridge src/bridge.rs --header > path/to/bridge.rs.h +$ cxxbridge src/bridge.rs > path/to/bridge.rs.cc +``` + +The CXX repo maintains working Bazel `BUILD` and Buck `BUCK` targets for the +complete blobstore tutorial (chapter 3) for your reference, tested in CI. These +aren't meant to be directly what you use in your codebase, but serve as an +illustration of one possible working pattern. + +```python +# tools/bazel/rust_cxx_bridge.bzl + +load("@bazel_skylib//rules:run_binary.bzl", "run_binary") +load("@rules_cc//cc:defs.bzl", "cc_library") + +def rust_cxx_bridge(name, src, deps = []): + native.alias( + name = "%s/header" % name, + actual = src + ".h", + ) + + native.alias( + name = "%s/source" % name, + actual = src + ".cc", + ) + + run_binary( + name = "%s/generated" % name, + srcs = [src], + outs = [ + src + ".h", + src + ".cc", + ], + args = [ + "$(location %s)" % src, + "-o", + "$(location %s.h)" % src, + "-o", + "$(location %s.cc)" % src, + ], + tool = "//:codegen", + ) + + cc_library( + name = name, + srcs = [src + ".cc"], + deps = deps + [":%s/include" % name], + ) + + cc_library( + name = "%s/include" % name, + hdrs = [src + ".h"], + ) +``` + +```python +# demo/BUILD + +load("@rules_cc//cc:defs.bzl", "cc_library") +load("@rules_rust//rust:defs.bzl", "rust_binary") +load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge") + +rust_binary( + name = "demo", + srcs = glob(["src/**/*.rs"]), + deps = [ + ":blobstore-sys", + ":bridge", + "//:cxx", + ], +) + +rust_cxx_bridge( + name = "bridge", + src = "src/main.rs", + deps = [":blobstore-include"], +) + +cc_library( + name = "blobstore-sys", + srcs = ["src/blobstore.cc"], + deps = [ + ":blobstore-include", + ":bridge/include", + ], +) + +cc_library( + name = "blobstore-include", + hdrs = ["include/blobstore.h"], + deps = ["//:core"], +) +``` diff --git a/vendor/cxx/book/src/build/cargo.md b/vendor/cxx/book/src/build/cargo.md new file mode 100644 index 000000000..82ccfb500 --- /dev/null +++ b/vendor/cxx/book/src/build/cargo.md @@ -0,0 +1,306 @@ +{{#title Cargo-based setup — Rust ♡ C++}} +# Cargo-based builds + +As one aspect of delivering a good Rust–C++ interop experience, CXX turns +Cargo into a quite usable build system for C++ projects published as a +collection of crates.io packages, including a consistent and frictionless +experience `#include`-ing C++ headers across dependencies. + +## Canonical setup + +CXX's integration with Cargo is handled through the [cxx-build] crate. + +[cxx-build]: https://docs.rs/cxx-build + +```toml,hidelines +## Cargo.toml +# [package] +# name = "..." +# version = "..." +# edition = "2018" + +[dependencies] +cxx = "1.0" + +[build-dependencies] +cxx-build = "1.0" +``` + +The canonical build script is as follows. The indicated line returns a +[`cc::Build`] instance (from the usual widely used `cc` crate) on which you can +set up any additional source files and compiler flags as normal. + +[`cc::Build`]: https://docs.rs/cc/1.0/cc/struct.Build.html + +```rust,noplayground +// build.rs + +fn main() { + cxx_build::bridge("src/main.rs") // returns a cc::Build + .file("src/demo.cc") + .flag_if_supported("-std=c++11") + .compile("cxxbridge-demo"); + + println!("cargo:rerun-if-changed=src/main.rs"); + println!("cargo:rerun-if-changed=src/demo.cc"); + println!("cargo:rerun-if-changed=include/demo.h"); +} +``` + +The `rerun-if-changed` lines are optional but make it so that Cargo does not +spend time recompiling your C++ code when only non-C++ code has changed since +the previous Cargo build. By default without any `rerun-if-changed`, Cargo will +re-execute the build script after *any* file changed in the project. + +If stuck, try comparing what you have against the *demo/* directory of the CXX +GitHub repo, which maintains a working Cargo-based setup for the blobstore +tutorial (chapter 3). + +## Header include paths + +With cxx-build, by default your include paths always start with the crate name. +This applies to both `#include` within your C++ code, and `include!` in the +`extern "C++"` section of your Rust cxx::bridge. + +Your crate name is determined by the `name` entry in Cargo.toml. + +For example if your crate is named `yourcratename` and contains a C++ header +file `path/to/header.h` relative to Cargo.toml, that file will be includable as: + +```cpp +#include "yourcratename/path/to/header.h" +``` + +A crate can choose a prefix for its headers that is different from the crate +name by modifying **[`CFG.include_prefix`][CFG]** from build.rs: + +[CFG]: https://docs.rs/cxx-build/*/cxx_build/static.CFG.html + +```rust,noplayground +// build.rs + +use cxx_build::CFG; + +fn main() { + CFG.include_prefix = "my/project"; + + cxx_build::bridge(...)... +} +``` + +Subsequently the header located at `path/to/header.h` would now be includable +as: + +```cpp +#include "my/project/path/to/header.h" +``` + +The empty string `""` is a valid include prefix and will make it possible to +have `#include "path/to/header.h"`. However, if your crate is a library, be +considerate of possible name collisions that may occur in downstream crates. If +using an empty include prefix, you'll want to make sure your headers' local path +within the crate is sufficiently namespaced or unique. + +## Including generated code + +If your `#[cxx::bridge]` module contains an `extern "Rust"` block i.e. types or +functions exposed from Rust to C++, or any shared data structures, the +CXX-generated C++ header declaring those things is available using a `.rs.h` +extension on the Rust source file's name. + +```cpp +// the header generated from path/to/lib.rs +#include "yourcratename/path/to/lib.rs.h" +``` + +For giggles, it's also available using just a plain `.rs` extension as if you +were including the Rust file directly. Use whichever you find more palatable. + +```cpp +#include "yourcratename/path/to/lib.rs" +``` + +## Including headers from dependencies + +You get to include headers from your dependencies, both handwritten ones +contained as `.h` files in their Cargo package, as well as CXX-generated ones. + +It works the same as an include of a local header: use the crate name (or their +include\_prefix if their crate changed it) followed by the relative path of the +header within the crate. + +```cpp +#include "dependencycratename/path/to/their/header.h` +``` + +Note that cross-crate imports are only made available between **direct +dependencies**. You must directly depend on the other crate in order to #include +its headers; a transitive dependency is not sufficient. + +Additionally, headers from a direct dependency are only importable if the +dependency's Cargo.toml manifest contains a `links` key. If not, its headers +will not be importable from outside of the same crate. See *[the `links` +manifest key][links]* in the Cargo reference. + +[links]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key + +<br><br><br> + +# Advanced features + +The following CFG settings are only relevant to you if you are writing a library +that needs to support downstream crates `#include`-ing its C++ public headers. + +## Publicly exporting header directories + +**[`CFG.exported_header_dirs`][CFG]** (vector of absolute paths) defines a set +of additional directories from which the current crate, directly dependent +crates, and further crates to which this crate's headers are exported (more +below) will be able to `#include` headers. + +Adding a directory to `exported_header_dirs` is similar to adding it to the +current build via the `cc` crate's [`Build::include`], but *also* makes the +directory available to downstream crates that want to `#include` one of the +headers from your crate. If the dir were added only using `Build::include`, the +downstream crate including your header would need to manually add the same +directory to their own build as well. + +[`Build::include`]: https://docs.rs/cc/1/cc/struct.Build.html#method.include + +When using `exported_header_dirs`, your crate must also set a `links` key for +itself in Cargo.toml. See [*the `links` manifest key*][links]. The reason is +that Cargo imposes no ordering on the execution of build scripts without a +`links` key, which means the downstream crate's build script might otherwise +execute before yours decides what to put into `exported_header_dirs`. + +### Example + +One of your crate's headers wants to include a system library, such as `#include +"Python.h"`. + +```rust,noplayground +// build.rs + +use cxx_build::CFG; +use std::path::PathBuf; + +fn main() { + let python3 = pkg_config::probe_library("python3").unwrap(); + let python_include_paths = python3.include_paths.iter().map(PathBuf::as_path); + CFG.exported_header_dirs.extend(python_include_paths); + + cxx_build::bridge("src/bridge.rs").compile("demo"); +} +``` + +### Example + +Your crate wants to rearrange the headers that it exports vs how they're laid +out locally inside the crate's source directory. + +Suppose the crate as published contains a file at `./include/myheader.h` but +wants it available to downstream crates as `#include "foo/v1/public.h"`. + +```rust,noplayground +// build.rs + +use cxx_build::CFG; +use std::path::Path; +use std::{env, fs}; + +fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + let headers = Path::new(&out_dir).join("headers"); + CFG.exported_header_dirs.push(&headers); + + // We contain `include/myheader.h` locally, but + // downstream will use `#include "foo/v1/public.h"` + let foo = headers.join("foo").join("v1"); + fs::create_dir_all(&foo).unwrap(); + fs::copy("include/myheader.h", foo.join("public.h")).unwrap(); + + cxx_build::bridge("src/bridge.rs").compile("demo"); +} +``` + +## Publicly exporting dependencies + +**[`CFG.exported_header_prefixes`][CFG]** (vector of strings) each refer to the +`include_prefix` of one of your direct dependencies, or a prefix thereof. They +describe which of your dependencies participate in your crate's C++ public API, +as opposed to private use by your crate's implementation. + +As a general rule, if one of your headers `#include`s something from one of your +dependencies, you need to put that dependency's `include_prefix` into +`CFG.exported_header_prefixes` (*or* their `links` key into +`CFG.exported_header_links`; see below). On the other hand if only your C++ +implementation files and *not* your headers are importing from the dependency, +you do not export that dependency. + +The significance of exported headers is that if downstream code (crate **𝒜**) +contains an `#include` of a header from your crate (**ℬ**) and your header +contains an `#include` of something from your dependency (**𝒞**), the exported +dependency **𝒞** becomes available during the downstream crate **𝒜**'s build. +Otherwise the downstream crate **𝒜** doesn't know about **𝒞** and wouldn't be +able to find what header your header is referring to, and would fail to build. + +When using `exported_header_prefixes`, your crate must also set a `links` key +for itself in Cargo.toml. + +### Example + +Suppose you have a crate with 5 direct dependencies and the `include_prefix` for +each one are: + +- "crate0" +- "group/api/crate1" +- "group/api/crate2" +- "group/api/contrib/crate3" +- "detail/crate4" + +Your header involves types from the first four so we re-export those as part of +your public API, while crate4 is only used internally by your cc file not your +header, so we do not export: + +```rust,noplayground +// build.rs + +use cxx_build::CFG; + +fn main() { + CFG.exported_header_prefixes = vec!["crate0", "group/api"]; + + cxx_build::bridge("src/bridge.rs") + .file("src/impl.cc") + .compile("demo"); +} +``` + +<br> + +For more fine grained control, there is **[`CFG.exported_header_links`][CFG]** +(vector of strings) which each refer to the `links` attribute ([*the `links` +manifest key*][links]) of one of your crate's direct dependencies. + +This achieves an equivalent result to `CFG.exported_header_prefixes` by +re-exporting a C++ dependency as part of your crate's public API, except with +finer control for cases when multiple crates might be sharing the same +`include_prefix` and you'd like to export some but not others. Links attributes +are guaranteed to be unique identifiers by Cargo. + +When using `exported_header_links`, your crate must also set a `links` key for +itself in Cargo.toml. + +### Example + +```rust,noplayground +// build.rs + +use cxx_build::CFG; + +fn main() { + CFG.exported_header_links.push("git2"); + + cxx_build::bridge("src/bridge.rs").compile("demo"); +} +``` diff --git a/vendor/cxx/book/src/build/cmake.md b/vendor/cxx/book/src/build/cmake.md new file mode 100644 index 000000000..478552e7f --- /dev/null +++ b/vendor/cxx/book/src/build/cmake.md @@ -0,0 +1,47 @@ +{{#title CMake — Rust ♡ C++}} +# CMake + +There is not an officially endorsed CMake setup for CXX, but a few developers +have shared one that they got working. You can try one of these as a starting +point. If you feel that you have arrived at a CMake setup that is superior to +what is available in these links, feel free to make a PR adding it to this list. + +<br> + +--- + +- **<https://github.com/XiangpengHao/cxx-cmake-example>** + + - Supports cross-language link time optimization (LTO) + +--- + +- **<https://github.com/david-cattermole/cxx-demo-example>** + + - Includes a cbindgen component + - Tested on Windows 10 with MSVC, and on Linux + +--- + +- **<https://github.com/trondhe/rusty_cmake>** + + - Alias target that can be linked into a C++ project + - Tested on Windows 10 with GNU target, and on Linux + +--- + +- **<https://github.com/geekbrother/cxx-corrosion-cmake>** + + - Improved rusty_cmake CMake file to use modern C++ + - Rich examples of using different primitive types and Rust's Result return to C++ + - MacOS and Linux only + +--- + +- **<https://github.com/paandahl/cpp-with-rust>** + + - Same blobstore example as the official demo, but inverted languages + - Minimal CMake configuration + - Tested on Linux, macOS, and Windows + +--- diff --git a/vendor/cxx/book/src/build/other.md b/vendor/cxx/book/src/build/other.md new file mode 100644 index 000000000..af835e658 --- /dev/null +++ b/vendor/cxx/book/src/build/other.md @@ -0,0 +1,81 @@ +{{#title Other build systems — Rust ♡ C++}} +# Some other build system + +You will need to achieve at least these three things: + +- Produce the CXX-generated C++ bindings code. +- Compile the generated C++ code. +- Link the resulting objects together with your other C++ and Rust objects. + +*Not all build systems are created equal. If you're hoping to use a build system +from the '90s, especially if you're hoping to overlaying the limitations of 2 or +more build systems (like automake+cargo) and expect to solve them +simultaneously, then be mindful that your expectations are set accordingly and +seek sympathy from those who have imposed the same approach on themselves.* + +### Producing the generated code + +CXX's Rust code generation automatically happens when the `#[cxx::bridge]` +procedural macro is expanded during the normal Rust compilation process, so no +special build steps are required there. + +But the C++ side of the bindings needs to be generated. Your options are: + +- Use the `cxxbridge` command, which is a standalone command line interface to + the CXX C++ code generator. Wire up your build system to compile and invoke + this tool. + + ```console + $ cxxbridge src/bridge.rs --header > path/to/bridge.rs.h + $ cxxbridge src/bridge.rs > path/to/bridge.rs.cc + ``` + + It's packaged as the `cxxbridge-cmd` crate on crates.io or can be built from + the *gen/cmd/* directory of the CXX GitHub repo. + +- Or, build your own code generator frontend on top of the [cxx-gen] crate. This + is currently unofficial and unsupported. + +[cxx-gen]: https://docs.rs/cxx-gen + +### Compiling C++ + +However you like. We can provide no guidance. + +### Linking the C++ and Rust together + +When linking a binary which contains mixed Rust and C++ code, you will have to +choose between using the Rust toolchain (`rustc`) or the C++ toolchain which you +may already have extensively tuned. + +Rust does not generate simple standalone `.o` files, so you can't just throw the +Rust-generated code into your existing C++ toolchain linker. Instead you need to +choose one of these options: + +* Use `rustc` as the final linker. Pass any non-Rust libraries using `-L + <directory>` and `-l<library>` rustc arguments, and/or `#[link]` directives in + your Rust code. If you need to link against C/C++ `.o` files you can use + `-Clink-arg=file.o`. + +* Use your C++ linker. In this case, you first need to use `rustc` and/or + `cargo` to generate a _single_ Rust `staticlib` target and pass that into your + foreign linker invocation. + + * If you need to link multiple Rust subsystems, you will need to generate a + _single_ `staticlib` perhaps using lots of `extern crate` statements to + include multiple Rust `rlib`s. Multiple Rust `staticlib` files are likely + to conflict. + +Passing Rust `rlib`s directly into your non-Rust linker is not supported (but +apparently sometimes works). + +See the [Rust reference's *Linkage*][linkage] page for some general information +here. + +[linkage]: https://doc.rust-lang.org/reference/linkage.html + +The following open rust-lang issues might hold more recent guidance or +inspiration: [rust-lang/rust#73632], [rust-lang/rust#73295]. + +[rust-lang/rust#73632]: https://github.com/rust-lang/rust/issues/73632 +[rust-lang/rust#73295]: https://github.com/rust-lang/rust/issues/73295 diff --git a/vendor/cxx/book/src/building.md b/vendor/cxx/book/src/building.md new file mode 100644 index 000000000..c75939e0d --- /dev/null +++ b/vendor/cxx/book/src/building.md @@ -0,0 +1,20 @@ +{{#title Multi-language build system options — Rust ♡ C++}} +# Multi-language build system options + +CXX is designed to be convenient to integrate into a variety of build systems. + +If you are working in a project that does not already have a preferred build +system for its C++ code *or* which will be relying heavily on open source +libraries from the Rust package registry, you're likely to have the easiest +experience with Cargo which is the build system commonly used by open source +Rust projects. Refer to the ***[Cargo](build/cargo.md)*** chapter about CXX's +Cargo support. + +Among build systems designed for first class multi-language support, Bazel is a +solid choice. Refer to the ***[Bazel](build/bazel.md)*** chapter. + +If your codebase is already invested in CMake, refer to the +***[CMake](build/cmake.md)*** chapter. + +If you have some other build system that you'd like to try to make work with +CXX, see [this page](build/other.md) for notes. diff --git a/vendor/cxx/book/src/concepts.md b/vendor/cxx/book/src/concepts.md new file mode 100644 index 000000000..75daedde1 --- /dev/null +++ b/vendor/cxx/book/src/concepts.md @@ -0,0 +1,85 @@ +{{#title Core concepts — Rust ♡ C++}} +# Core concepts + +This page is a brief overview of the major concepts of CXX, enough so that you +recognize the shape of things as you read the tutorial and following chapters. + +In CXX, the language of the FFI boundary involves 3 kinds of items: + +- **Shared structs** — data structures whose fields are made visible to + both languages. The definition written within cxx::bridge in Rust is usually + the single source of truth, though there are ways to do sharing based on a + bindgen-generated definition with C++ as source of truth. + +- **Opaque types** — their fields are secret from the other language. + These cannot be passed across the FFI by value but only behind an indirection, + such as a reference `&`, a Rust `Box`, or a C++ `unique_ptr`. Can be a type + alias for an arbitrarily complicated generic language-specific type depending + on your use case. + +- **Functions** — implemented in either language, callable from the other + language. + +```rust,noplayground,focuscomment +# #[cxx::bridge] +# mod ffi { + // Any shared structs, whose fields will be visible to both languages. +# struct BlobMetadata { +# size: usize, +# tags: Vec<String>, +# } +# +# extern "Rust" { + // Zero or more opaque types which both languages can pass around + // but only Rust can see the fields. +# type MultiBuf; +# + // Functions implemented in Rust. +# fn next_chunk(buf: &mut MultiBuf) -> &[u8]; +# } +# +# unsafe extern "C++" { + // One or more headers with the matching C++ declarations for the + // enclosing extern "C++" block. Our code generators don't read it + // but it gets #include'd and used in static assertions to ensure + // our picture of the FFI boundary is accurate. +# include!("demo/include/blobstore.h"); +# + // Zero or more opaque types which both languages can pass around + // but only C++ can see the fields. +# type BlobstoreClient; +# + // Functions implemented in C++. +# fn new_blobstore_client() -> UniquePtr<BlobstoreClient>; +# fn put(&self, parts: &mut MultiBuf) -> u64; +# fn tag(&self, blobid: u64, tag: &str); +# fn metadata(&self, blobid: u64) -> BlobMetadata; +# } +# } +``` + +Within the `extern "Rust"` part of the CXX bridge we list the types and +functions for which Rust is the source of truth. These all implicitly refer to +the `super` module, the parent module of the CXX bridge. You can think of the +two items listed in the example above as being like `use super::MultiBuf` and +`use super::next_chunk` except re-exported to C++. The parent module will either +contain the definitions directly for simple things, or contain the relevant +`use` statements to bring them into scope from elsewhere. + +Within the `extern "C++"` part, we list types and functions for which C++ is the +source of truth, as well as the header(s) that declare those APIs. In the future +it's possible that this section could be generated bindgen-style from the +headers but for now we need the signatures written out; static assertions verify +that they are accurate. + +<br><br> + +Be aware that the design of this library is intentionally restrictive and +opinionated! It isn't a goal to be flexible enough to handle an arbitrary +signature in either language. Instead this project is about carving out a highly +expressive set of functionality about which we can make powerful safety +guarantees today and extend over time. You may find that it takes some practice +to use CXX bridge effectively as it won't work in all the ways that you may be +used to. + +<br> diff --git a/vendor/cxx/book/src/context.md b/vendor/cxx/book/src/context.md new file mode 100644 index 000000000..516ee91f2 --- /dev/null +++ b/vendor/cxx/book/src/context.md @@ -0,0 +1,118 @@ +{{#title Other Rust–C++ interop tools — Rust ♡ C++}} +# Context: other Rust–C++ interop tools + +When it comes to interacting with an idiomatic Rust API or idiomatic C++ API +from the other language, the generally applicable approaches outside of the CXX +crate are: + +- Build a C-compatible wrapper around the code (expressed using `extern "C"` + signatures, primitives, C-compatible structs, raw pointers). Translate that + manually to equivalent `extern "C"` declarations in the other language and + keep them in sync. Preferably, build a safe/idiomatic wrapper around the + translated `extern "C"` signatures for callers to use. + +- Build a C wrapper around the C++ code and use **[bindgen]** to translate that + programmatically to `extern "C"` Rust signatures. Preferably, build a + safe/idiomatic Rust wrapper on top. + +- Build a C-compatible Rust wrapper around the Rust code and use **[cbindgen]** + to translate that programmatically to an `extern "C"` C++ header. Preferably, + build an idiomatic C++ wrapper. + +**If the code you are binding is already *"effectively C"*, the above has you +covered.** You should use bindgen or cbindgen, or manually translated C +signatures if there aren't too many and they seldom change. + +[bindgen]: https://github.com/rust-lang/rust-bindgen +[cbindgen]: https://github.com/eqrion/cbindgen + +## C++ vs C + +Bindgen has some basic support for C++. It can reason about classes, member +functions, and the layout of templated types. However, everything it does +related to C++ is best-effort only. Bindgen starts from a point of wanting to +generate declarations for everything, so any C++ detail that it hasn't +implemented will cause a crash if you are lucky ([bindgen#388]) or more likely +silently emit an incompatible signature ([bindgen#380], [bindgen#607], +[bindgen#652], [bindgen#778], [bindgen#1194]) which will do arbitrary +memory-unsafe things at runtime whenever called. + +[bindgen#388]: https://github.com/rust-lang/rust-bindgen/issues/388 +[bindgen#380]: https://github.com/rust-lang/rust-bindgen/issues/380 +[bindgen#607]: https://github.com/rust-lang/rust-bindgen/issues/607 +[bindgen#652]: https://github.com/rust-lang/rust-bindgen/issues/652 +[bindgen#778]: https://github.com/rust-lang/rust-bindgen/issues/778 +[bindgen#1194]: https://github.com/rust-lang/rust-bindgen/issues/1194 + +Thus using bindgen correctly requires not just juggling all your pointers +correctly at the language boundary, but also understanding ABI details and their +workarounds and reliably applying them. For example, the programmer will +discover that their program sometimes segfaults if they call a function that +returns std::unique\_ptr\<T\> through bindgen. Why? Because unique\_ptr, despite +being "just a pointer", has a different ABI than a pointer or a C struct +containing a pointer ([bindgen#778]) and is not directly expressible in Rust. +Bindgen emitted something that *looks* reasonable and you will have a hell of a +time in gdb working out what went wrong. Eventually people learn to avoid +anything involving a non-trivial copy constructor, destructor, or inheritance, +and instead stick to raw pointers and primitives and trivial structs only +— in other words C. + +## Geometric intuition for why there is so much opportunity for improvement + +The CXX project attempts a different approach to C++ FFI. + +Imagine Rust and C and C++ as three vertices of a scalene triangle, with length +of the edges being related to similarity of the languages when it comes to +library design. + +The most similar pair (the shortest edge) is Rust–C++. These languages +have largely compatible concepts of things like ownership, vectors, strings, +fallibility, etc that translate clearly from signatures in either language to +signatures in the other language. + +When we make a binding for an idiomatic C++ API using bindgen, and we fall down +to raw pointers and primitives and trivial structs as described above, what we +are really doing is coding the two longest edges of the triangle: getting from +C++ down to C, and C back up to Rust. The Rust–C edge always involves a +great deal of `unsafe` code, and the C++–C edge similarly requires care +just for basic memory safety. Something as basic as "how do I pass ownership of +a string to the other language?" becomes a strap-yourself-in moment, +particularly for someone not already an expert in one or both sides. + +You should think of the `cxx` crate as being the midpoint of the Rust–C++ +edge. Rather than coding the two long edges, you will code half the short edge +in Rust and half the short edge in C++, in both cases with the library playing +to the strengths of the Rust type system *and* the C++ type system to help +assure correctness. + +If you've already been through the tutorial in the previous chapter, take a +moment to appreciate that the C++ side *really* looks like we are just writing +C++ and the Rust side *really* looks like we are just writing Rust. Anything you +could do wrong in Rust, and almost anything you could reasonably do wrong in +C++, will be caught by the compiler. This highlights that we are on the "short +edge of the triangle". + +But it all still boils down to the same things: it's still FFI from one piece of +native code to another, nothing is getting serialized or allocated or +runtime-checked in between. + +## Role of CXX + +The role of CXX is to capture the language boundary with more fidelity than what +`extern "C"` is able to represent. You can think of CXX as being a replacement +for `extern "C"` in a sense. + +From this perspective, CXX is a lower level tool than the bindgens. Just as +bindgen and cbindgen are built on top of `extern "C"`, it makes sense to think +about higher level tools built on top of CXX. Such a tool might consume a C++ +header and/or Rust module (and/or IDL like Thrift) and emit the corresponding +safe cxx::bridge language boundary, leveraging CXX's static analysis and +underlying implementation of that boundary. We are beginning to see this space +explored by the [autocxx] tool, though nothing yet ready for broad use in the +way that CXX on its own is. + +[autocxx]: https://github.com/google/autocxx + +But note in other ways CXX is higher level than the bindgens, with rich support +for common standard library types. CXX's types serve as an intuitive vocabulary +for designing a good boundary between components in different languages. diff --git a/vendor/cxx/book/src/cxx.png b/vendor/cxx/book/src/cxx.png Binary files differnew file mode 100644 index 000000000..07118aafb --- /dev/null +++ b/vendor/cxx/book/src/cxx.png diff --git a/vendor/cxx/book/src/extern-c++.md b/vendor/cxx/book/src/extern-c++.md new file mode 100644 index 000000000..11ed7b54e --- /dev/null +++ b/vendor/cxx/book/src/extern-c++.md @@ -0,0 +1,352 @@ +{{#title extern "C++" — Rust ♡ C++}} +# extern "C++" + +```rust,noplayground +#[cxx::bridge] +mod ffi { + extern "C++" { + include!("path/to/header.h"); + include!("path/to/another.h"); + + ... + } +} +``` + +The `extern "C++"` section of a CXX bridge declares C++ types and signatures to +be made available to Rust, and gives the paths of the header(s) which contain +the corresponding C++ declarations. + +A bridge module may contain zero or more extern "C++" blocks. + +## Opaque C++ types + +Type defined in C++ that are made available to Rust, but only behind an +indirection. + +```rust,noplayground +# #[cxx::bridge] +# mod ffi { + extern "C++" { + # include!("path/to/header.h"); + # + type MyType; + type MyOtherType; + } +# } +``` + +For example in the ***[Tutorial](tutorial.md)*** we saw `BlobstoreClient` +implemented as an opaque C++ type. The blobstore client was created in C++ and +returned to Rust by way of a UniquePtr. + +**Mutability:** Unlike extern Rust types and shared types, an extern C++ type is +not permitted to be passed by plain mutable reference `&mut MyType` across the +FFI bridge. For mutation support, the bridge is required to use `Pin<&mut +MyType>`. This is to safeguard against things like mem::swap-ing the contents of +two mutable references, given that Rust doesn't have information about the size +of the underlying object and couldn't invoke an appropriate C++ move constructor +anyway. + +**Thread safety:** Be aware that CXX does not assume anything about the thread +safety of your extern C++ types. In other words the `MyType` etc bindings which +CXX produces for you in Rust *do not* come with `Send` and `Sync` impls. If you +are sure that your C++ type satisfies the requirements of `Send` and/or `Sync` +and need to leverage that fact from Rust, you must provide your own unsafe +marker trait impls. + +```rust,noplayground +# #[cxx::bridge] +# mod ffi { +# extern "C++" { +# include!("path/to/header.h"); +# +# type MyType; +# } +# } +# +/// The C++ implementation of MyType is thread safe. +unsafe impl Send for ffi::MyType {} +unsafe impl Sync for ffi::MyType {} +``` + +Take care in doing this because thread safety in C++ can be extremely tricky to +assess if you are coming from a Rust background. For example the +`BlobstoreClient` type in the tutorial is *not thread safe* despite doing only +completely innocuous things in its implementation. Concurrent calls to the `tag` +member function trigger a data race on the `blobs` map. + +## Functions and member functions + +This largely follows the same principles as ***[extern +"Rust"](extern-rust.md)*** functions and methods. In particular, any signature +with a `self` parameter is interpreted as a C++ non-static member function and +exposed to Rust as a method. + +The programmer **does not** need to promise that the signatures they have typed +in are accurate; that would be unreasonable. CXX performs static assertions that +the signatures exactly correspond with what is declared in C++. Rather, the +programmer is only on the hook for things that C++'s static information is not +precise enough to capture, i.e. things that would only be represented at most by +comments in the C++ code unintelligible to a static assertion: namely whether +the C++ function is safe or unsafe to be called from Rust. + +**Safety:** the extern "C++" block is responsible for deciding whether to expose +each signature inside as safe-to-call or unsafe-to-call. If an extern block +contains at least one safe-to-call signature, it must be written as an `unsafe +extern` block, which serves as an item level unsafe block to indicate that an +unchecked safety claim is being made about the contents of the block. + +```rust,noplayground +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + # include!("path/to/header.h"); + # + fn f(); // safe to call + } + + extern "C++" { + unsafe fn g(); // unsafe to call + } +} +``` + +## Lifetimes + +C++ types holding borrowed data may be described naturally in Rust by an extern +type with a generic lifetime parameter. For example in the case of the following +pair of types: + +```cpp +// header.h + +class Resource; + +class TypeContainingBorrow { + TypeContainingBorrow(const Resource &res) : res(res) {} + const Resource &res; +}; + +std::shared_ptr<TypeContainingBorrow> create(const Resource &res); +``` + +we'd want to expose this to Rust as: + +```rust,noplayground +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + # include!("path/to/header.h"); + # + type Resource; + type TypeContainingBorrow<'a>; + + fn create<'a>(res: &'a Resource) -> SharedPtr<TypeContainingBorrow<'a>>; + + // or with lifetime elision: + fn create(res: &Resource) -> SharedPtr<TypeContainingBorrow>; + } +} +``` + +## Reusing existing binding types + +Extern C++ types support a syntax for declaring that a Rust binding of the +correct C++ type already exists outside of the current bridge module. This +avoids generating a fresh new binding which Rust's type system would consider +non-interchangeable with the first. + +```rust,noplayground +#[cxx::bridge(namespace = "path::to")] +mod ffi { + extern "C++" { + type MyType = crate::existing::MyType; + } + + extern "Rust" { + fn f(x: &MyType) -> usize; + } +} +``` + +In this case rather than producing a unique new Rust type `ffi::MyType` for the +Rust binding of C++'s `::path::to::MyType`, CXX will reuse the already existing +binding at `crate::existing::MyType` in expressing the signature of `f` and any +other uses of `MyType` within the bridge module. + +CXX safely validates that `crate::existing::MyType` is in fact a binding for the +right C++ type `::path::to::MyType` by generating a static assertion based on +`crate::existing::MyType`'s implementation of [`ExternType`], which is a trait +automatically implemented by CXX for bindings that it generates but can also be +manually implemented as described below. + +[`ExternType`]: https://docs.rs/cxx/*/cxx/trait.ExternType.html + +`ExternType` serves the following two related use cases. + +#### Safely unifying occurrences of an extern type across bridges + +In the following snippet, two #\[cxx::bridge\] invocations in different files +(possibly different crates) both contain function signatures involving the same +C++ type `example::Demo`. If both were written just containing `type Demo;`, +then both macro expansions would produce their own separate Rust type called +`Demo` and thus the compiler wouldn't allow us to take the `Demo` returned by +`file1::ffi::create_demo` and pass it as the `Demo` argument accepted by +`file2::ffi::take_ref_demo`. Instead, one of the two `Demo`s has been defined as +an extern type alias of the other, making them the same type in Rust. + +```rust,noplayground +// file1.rs +#[cxx::bridge(namespace = "example")] +pub mod ffi { + unsafe extern "C++" { + type Demo; + + fn create_demo() -> UniquePtr<Demo>; + } +} +``` + +```rust,noplayground +// file2.rs +#[cxx::bridge(namespace = "example")] +pub mod ffi { + unsafe extern "C++" { + type Demo = crate::file1::ffi::Demo; + + fn take_ref_demo(demo: &Demo); + } +} +``` + +#### Integrating with bindgen-generated or handwritten unsafe bindings + +Handwritten `ExternType` impls make it possible to plug in a data structure +emitted by bindgen as the definition of a C++ type emitted by CXX. + +By writing the unsafe `ExternType` impl, the programmer asserts that the C++ +namespace and type name given in the type id refers to a C++ type that is +equivalent to Rust type that is the `Self` type of the impl. + +```rust,noplayground +mod folly_sys; // the bindgen-generated bindings + +use cxx::{type_id, ExternType}; + +unsafe impl ExternType for folly_sys::StringPiece { + type Id = type_id!("folly::StringPiece"); + type Kind = cxx::kind::Opaque; +} + +#[cxx::bridge(namespace = "folly")] +pub mod ffi { + unsafe extern "C++" { + include!("rust_cxx_bindings.h"); + + type StringPiece = crate::folly_sys::StringPiece; + + fn print_string_piece(s: &StringPiece); + } +} + +// Now if we construct a StringPiece or obtain one through one +// of the bindgen-generated signatures, we are able to pass it +// along to ffi::print_string_piece. +``` + +The `ExternType::Id` associated type encodes a type-level representation of the +type's C++ namespace and type name. It will always be defined using the +`type_id!` macro exposed in the cxx crate. + +The `ExternType::Kind` associated type will always be either +[`cxx::kind::Opaque`] or [`cxx::kind::Trivial`] identifying whether a C++ type +is soundly relocatable by Rust's move semantics. A C++ type is only okay to hold +and pass around by value in Rust if its [move constructor is trivial] and it has +no destructor. In CXX, these are called Trivial extern C++ types, while types +with nontrivial move behavior or a destructor must be considered Opaque and +handled by Rust only behind an indirection, such as a reference or UniquePtr. + +[`cxx::kind::Opaque`]: https://docs.rs/cxx/*/cxx/kind/enum.Opaque.html +[`cxx::kind::Trivial`]: https://docs.rs/cxx/*/cxx/kind/enum.Trivial.html +[move constructor is trivial]: https://en.cppreference.com/w/cpp/types/is_move_constructible + +If you believe your C++ type reflected by the ExternType impl is indeed fine to +hold by value and move in Rust, you can specify: + +```rust,noplayground +# unsafe impl cxx::ExternType for TypeName { +# type Id = cxx::type_id!("name::space::of::TypeName"); + type Kind = cxx::kind::Trivial; +# } +``` + +which will enable you to pass it into C++ functions by value, return it by +value, and include it in `struct`s that you have declared to `cxx::bridge`. Your +claim about the triviality of the C++ type will be checked by a `static_assert` +in the generated C++ side of the binding. + +## Explicit shim trait impls + +This is a somewhat niche feature, but important when you need it. + +CXX's support for C++'s std::unique\_ptr and std::vector is built on a set of +internal trait impls connecting the Rust API of UniquePtr and CxxVector to +underlying template instantiations performed by the C++ compiler. + +When reusing a binding type across multiple bridge modules as described in the +previous section, you may find that your code needs some trait impls which CXX +hasn't decided to generate. + +```rust,noplayground +#[cxx::bridge] +mod ffi1 { + extern "C++" { + include!("path/to/header.h"); + + type A; + type B; + + // Okay: CXX sees UniquePtr<B> using a type B defined within the same + // bridge, and automatically emits the right template instantiations + // corresponding to std::unique_ptr<B>. + fn get_b() -> UniquePtr<B>; + } +} + +#[cxx::bridge] +mod ffi2 { + extern "C++" { + type A = crate::ffi1::A; + + // Rust trait error: CXX processing this module has no visibility into + // whether template instantiations corresponding to std::unique_ptr<A> + // have already been emitted by the upstream library, so it does not + // emit them here. If the upstream library does not have any signatures + // involving UniquePtr<A>, an explicit instantiation of the template + // needs to be requested in one module or the other. + fn get_a() -> UniquePtr<A>; + } +} +``` + +You can request a specific template instantiation at a particular location in +the Rust crate hierarchy by writing `impl UniquePtr<A> {}` inside of the bridge +module which defines `A` but does not otherwise contain any use of +`UniquePtr<A>`. + +```rust,noplayground +#[cxx::bridge] +mod ffi1 { + extern "C++" { + include!("path/to/header.h"); + + type A; + type B; + + fn get_b() -> UniquePtr<B>; + } + + impl UniquePtr<A> {} // explicit instantiation +} +``` diff --git a/vendor/cxx/book/src/extern-rust.md b/vendor/cxx/book/src/extern-rust.md new file mode 100644 index 000000000..40f223759 --- /dev/null +++ b/vendor/cxx/book/src/extern-rust.md @@ -0,0 +1,165 @@ +{{#title extern "Rust" — Rust ♡ C++}} +# extern "Rust" + +```rust,noplayground +#[cxx::bridge] +mod ffi { + extern "Rust" { + + } +} +``` + +The `extern "Rust"` section of a CXX bridge declares Rust types and signatures +to be made available to C++. + +The CXX code generator uses your extern "Rust" section(s) to produce a C++ +header file containing the corresponding C++ declarations. The generated header +has the same path as the Rust source file containing the bridge, except with a +`.rs.h` file extension. + +A bridge module may contain zero or more extern "Rust" blocks. + +## Opaque Rust types + +Types defined in Rust that are made available to C++, but only behind an +indirection. + +```rust,noplayground +# #[cxx::bridge] +# mod ffi { + extern "Rust" { + type MyType; + type MyOtherType; + type OneMoreType<'a>; + } +# } +``` + +For example in the ***[Tutorial](tutorial.md)*** we saw `MultiBuf` used in this +way. Rust code created the `MultiBuf`, passed a `&mut MultiBuf` to C++, and C++ +later passed a `&mut MultiBuf` back across the bridge to Rust. + +Another example is the one on the ***[Box\<T\>](binding/box.md)*** page, which +exposes the Rust standard library's `std::fs::File` to C++ as an opaque type in +a similar way but with Box as the indirection rather than &mut. + +The types named as opaque types (`MyType` etc) refer to types in the `super` +module, the parent module of the CXX bridge. You can think of an opaque type `T` +as being like a re-export `use super::T` made available to C++ via the generated +header. + +Opaque types are currently required to be [`Sized`] and [`Unpin`]. In +particular, a trait object `dyn MyTrait` or slice `[T]` may not be used for an +opaque Rust type. These restrictions may be lifted in the future. + +[`Sized`]: https://doc.rust-lang.org/std/marker/trait.Sized.html +[`Unpin`]: https://doc.rust-lang.org/std/marker/trait.Unpin.html + +For now, types used as extern Rust types are required to be defined by the same +crate that contains the bridge using them. This restriction may be lifted in the +future. + +The bridge's parent module will contain the appropriate imports or definitions +for these types. + +```rust,noplayground +use path::to::MyType; + +pub struct MyOtherType { + ... +} +# +# #[cxx::bridge] +# mod ffi { +# extern "Rust" { +# type MyType; +# type MyOtherType; +# } +# } +``` + +## Functions + +Rust functions made callable to C++. + +Just like for opaque types, these functions refer implicitly to something in +scope in the `super` module, whether defined there or imported by some `use` +statement. + +```rust,noplayground +#[cxx::bridge] +mod ffi { + extern "Rust" { + type MyType; + fn f() -> Box<MyType>; + } +} + +struct MyType(i32); + +fn f() -> Box<MyType> { + return Box::new(MyType(1)); +} +``` + +Extern Rust function signature may consist of types defined in the bridge, +primitives, and [any of these additional bindings](bindings.md). + +## Methods + +Any signature with a `self` parameter is interpreted as a Rust method and +exposed to C++ as a non-static member function. + +```rust,noplayground +# #[cxx::bridge] +# mod ffi { + extern "Rust" { + type MyType; + fn f(&self) -> usize; + } +# } +``` + +The `self` parameter may be a shared reference `&self`, an exclusive reference +`&mut self`, or a pinned reference `self: Pin<&mut Self>`. A by-value `self` is +not currently supported. + +If the surrounding `extern "Rust"` block contains exactly one extern type, that +type is implicitly the receiver for a `&self` or `&mut self` method. If the +surrounding block contains *more than one* extern type, a receiver type must be +provided explicitly for the self parameter, or you can consider splitting into +multiple extern blocks. + +```rust,noplayground +# #[cxx::bridge] +# mod ffi { + extern "Rust" { + type First; + type Second; + fn bar(self: &First); + fn foo(self: &mut Second); + } +# } +``` + +## Functions with explicit lifetimes + +An extern Rust function signature is allowed to contain explicit lifetimes but +in this case the function must be declared unsafe-to-call. This is pretty +meaningless given we're talking about calls from C++, but at least it draws some +extra attention from the caller that they may be responsible for upholding some +atypical lifetime relationship. + +```rust,noplayground +#[cxx::bridge] +mod ffi { + extern "Rust" { + type MyType; + unsafe fn f<'a>(&'a self, s: &str) -> &'a str; + } +} +``` + +Bounds on a lifetime (like `<'a, 'b: 'a>`) are not currently supported. Nor are +type parameters or where-clauses. diff --git a/vendor/cxx/book/src/index.md b/vendor/cxx/book/src/index.md new file mode 100644 index 000000000..7add044c3 --- /dev/null +++ b/vendor/cxx/book/src/index.md @@ -0,0 +1,83 @@ +<div class="badges"> +<a href="https://github.com/dtolnay/cxx"><img src="https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github" alt="github" height="28" class="badge"></a><a href="https://crates.io/crates/cxx"><img src="https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust" alt="crates-io" height="28" class="badge"></a><a href="https://docs.rs/cxx"><img src="https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" alt="docs-rs" height="28" class="badge"></a> +</div> + +# CXX — safe interop between Rust and C++ + +This library provides a safe mechanism for calling C++ code from Rust and Rust +code from C++. It carves out a regime of commonality where Rust and C++ are +semantically very similar and guides the programmer to express their language +boundary effectively within this regime. CXX fills in the low level stuff so +that you get a safe binding, preventing the pitfalls of doing a foreign function +interface over unsafe C-style signatures. + +<div style="height:190px;width=718px;padding:44px 0 44px"> +<object type="image/svg+xml" data="overview.svg"></object> +</div> + +From a high level description of the language boundary, CXX uses static analysis +of the types and function signatures to protect both Rust's and C++'s +invariants. Then it uses a pair of code generators to implement the boundary +efficiently on both sides together with any necessary static assertions for +later in the build process to verify correctness. + +The resulting FFI bridge operates at zero or negligible overhead, i.e. no +copying, no serialization, no memory allocation, no runtime checks needed. + +The FFI signatures are able to use native data structures from whichever side +they please. In addition, CXX provides builtin bindings for key standard library +types like strings, vectors, Box, unique\_ptr, etc to expose an idiomatic API on +those types to the other language. + +## Example + +In this example we are writing a Rust application that calls a C++ client of a +large-file blobstore service. The blobstore supports a `put` operation for a +discontiguous buffer upload. For example we might be uploading snapshots of a +circular buffer which would tend to consist of 2 pieces, or fragments of a file +spread across memory for some other reason (like a rope data structure). + +```rust,noplayground +#[cxx::bridge] +mod ffi { + extern "Rust" { + type MultiBuf; + + fn next_chunk(buf: &mut MultiBuf) -> &[u8]; + } + + unsafe extern "C++" { + include!("example/include/blobstore.h"); + + type BlobstoreClient; + + fn new_blobstore_client() -> UniquePtr<BlobstoreClient>; + fn put(self: &BlobstoreClient, buf: &mut MultiBuf) -> Result<u64>; + } +} +``` + +Now we simply provide Rust definitions of all the things in the `extern "Rust"` +block and C++ definitions of all the things in the `extern "C++"` block, and get +to call back and forth safely. + +The [***Tutorial***](tutorial.md) chapter walks through a fleshed out version of +this blobstore example in full detail, including all of the Rust code and all of +the C++ code. The code is also provided in runnable form in the *demo* directory +of <https://github.com/dtolnay/cxx>. To try it out, run `cargo run` from that +directory. + +- [demo/src/main.rs](https://github.com/dtolnay/cxx/blob/master/demo/src/main.rs) +- [demo/include/blobstore.h](https://github.com/dtolnay/cxx/blob/master/demo/include/blobstore.h) +- [demo/src/blobstore.cc](https://github.com/dtolnay/cxx/blob/master/demo/src/blobstore.cc) + +The key takeaway, which is enabled by the CXX library, is that the Rust code in +main.rs is 100% ordinary safe Rust code working idiomatically with Rust types +while the C++ code in blobstore.cc is 100% ordinary C++ code working +idiomatically with C++ types. The Rust code feels like Rust and the C++ code +feels like C++, not like C-style "FFI glue". + +<br> + +***Chapter outline:** See the hamburger menu in the top left if you are on a +small screen and it didn't open with a sidebar by default.* diff --git a/vendor/cxx/book/src/overview.svg b/vendor/cxx/book/src/overview.svg new file mode 100644 index 000000000..df4fcf49e --- /dev/null +++ b/vendor/cxx/book/src/overview.svg @@ -0,0 +1,444 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="541.903pt" height="142.287pt" viewBox="0 0 541.903 142.287" version="1.1"> +<defs> +<g> +<symbol overflow="visible" id="glyph0-0"> +<path style="stroke:none;" d=""/> +</symbol> +<symbol overflow="visible" id="glyph0-1"> +<path style="stroke:none;" d="M 5.140625 -2.359375 L 6.234375 -2.359375 C 6.421875 -2.359375 6.890625 -2.359375 6.890625 -2.828125 C 6.890625 -3.296875 6.4375 -3.296875 6.234375 -3.296875 L 5.265625 -3.296875 L 5.515625 -5.46875 L 6.234375 -5.46875 C 6.421875 -5.46875 6.890625 -5.46875 6.890625 -5.921875 C 6.890625 -6.390625 6.4375 -6.390625 6.234375 -6.390625 L 5.65625 -6.390625 L 5.875 -8.125 C 5.9375 -8.59375 5.6875 -8.765625 5.421875 -8.765625 C 5.015625 -8.765625 4.984375 -8.390625 4.953125 -8.203125 L 4.71875 -6.390625 L 3.171875 -6.390625 L 3.40625 -8.125 C 3.453125 -8.59375 3.203125 -8.765625 2.9375 -8.765625 C 2.53125 -8.765625 2.5 -8.390625 2.46875 -8.203125 L 2.234375 -6.390625 L 1.140625 -6.390625 C 0.953125 -6.390625 0.484375 -6.390625 0.484375 -5.9375 C 0.484375 -5.46875 0.9375 -5.46875 1.140625 -5.46875 L 2.109375 -5.46875 L 1.84375 -3.296875 L 1.140625 -3.296875 C 0.953125 -3.296875 0.484375 -3.296875 0.484375 -2.84375 C 0.484375 -2.359375 0.9375 -2.359375 1.140625 -2.359375 L 1.71875 -2.359375 L 1.484375 -0.640625 C 1.40625 0 1.90625 0 1.953125 0 C 2.359375 0 2.390625 -0.375 2.421875 -0.5625 L 2.65625 -2.359375 L 4.203125 -2.359375 L 3.96875 -0.640625 C 3.890625 0 4.390625 0 4.4375 0 C 4.828125 0 4.875 -0.375 4.90625 -0.5625 Z M 3.046875 -5.46875 L 4.59375 -5.46875 L 4.328125 -3.296875 L 2.78125 -3.296875 Z M 3.046875 -5.46875 "/> +</symbol> +<symbol overflow="visible" id="glyph0-2"> +<path style="stroke:none;" d="M 6.21875 -9.125 C 6.421875 -9.125 6.796875 -9.125 6.796875 -9.53125 C 6.796875 -9.953125 6.421875 -9.953125 6.21875 -9.953125 L 3.734375 -9.953125 C 3.25 -9.953125 3.15625 -9.828125 3.15625 -9.359375 L 3.15625 0.609375 C 3.15625 1.046875 3.234375 1.1875 3.734375 1.1875 L 6.21875 1.1875 C 6.421875 1.1875 6.796875 1.1875 6.796875 0.78125 C 6.796875 0.359375 6.421875 0.359375 6.21875 0.359375 L 4.09375 0.359375 L 4.09375 -9.125 Z M 6.21875 -9.125 "/> +</symbol> +<symbol overflow="visible" id="glyph0-3"> +<path style="stroke:none;" d="M 4.21875 -9.359375 C 4.21875 -9.8125 4.125 -9.953125 3.640625 -9.953125 L 1.140625 -9.953125 C 0.953125 -9.953125 0.578125 -9.953125 0.578125 -9.53125 C 0.578125 -9.125 0.953125 -9.125 1.140625 -9.125 L 3.28125 -9.125 L 3.28125 0.359375 L 1.140625 0.359375 C 0.953125 0.359375 0.578125 0.359375 0.578125 0.78125 C 0.578125 1.1875 0.953125 1.1875 1.140625 1.1875 L 3.640625 1.1875 C 4.109375 1.1875 4.21875 1.0625 4.21875 0.609375 Z M 4.21875 -9.359375 "/> +</symbol> +<symbol overflow="visible" id="glyph0-4"> +<path style="stroke:none;" d="M 4.15625 -3.921875 L 6.203125 -3.921875 C 6.390625 -3.921875 6.84375 -3.921875 6.84375 -4.375 C 6.84375 -4.84375 6.390625 -4.84375 6.203125 -4.84375 L 4.15625 -4.84375 L 4.15625 -6.90625 C 4.15625 -7.078125 4.15625 -7.546875 3.703125 -7.546875 C 3.234375 -7.546875 3.234375 -7.09375 3.234375 -6.90625 L 3.234375 -4.84375 L 1.171875 -4.84375 C 0.984375 -4.84375 0.53125 -4.84375 0.53125 -4.390625 C 0.53125 -3.921875 0.96875 -3.921875 1.171875 -3.921875 L 3.234375 -3.921875 L 3.234375 -1.859375 C 3.234375 -1.671875 3.234375 -1.21875 3.6875 -1.21875 C 4.15625 -1.21875 4.15625 -1.65625 4.15625 -1.859375 Z M 4.15625 -3.921875 "/> +</symbol> +<symbol overflow="visible" id="glyph1-0"> +<path style="stroke:none;" d=""/> +</symbol> +<symbol overflow="visible" id="glyph1-1"> +<path style="stroke:none;" d="M 5.75 -1.546875 C 5.09375 -1.015625 4.359375 -0.75 3.5625 -0.75 C 2.359375 -0.75 1.59375 -1.8125 1.59375 -3.203125 C 1.59375 -4.390625 2.171875 -5.6875 3.59375 -5.6875 C 4.5625 -5.6875 4.96875 -5.46875 5.578125 -5.046875 L 5.75 -5.984375 C 4.921875 -6.46875 4.453125 -6.578125 3.59375 -6.578125 C 1.625 -6.578125 0.5 -4.828125 0.5 -3.203125 C 0.5 -1.359375 1.828125 0.140625 3.546875 0.140625 C 4.25 0.140625 5.046875 -0.03125 5.84375 -0.609375 C 5.84375 -0.640625 5.796875 -1.09375 5.78125 -1.140625 Z M 5.75 -1.546875 "/> +</symbol> +<symbol overflow="visible" id="glyph1-2"> +<path style="stroke:none;" d="M 3.640625 -3.28125 L 6.1875 -6.375 L 4.984375 -6.375 L 3.171875 -4.046875 L 1.296875 -6.375 L 0.078125 -6.375 L 2.6875 -3.28125 L 0 0 L 1.1875 0 L 3.171875 -2.671875 L 5.203125 0 L 6.40625 0 Z M 3.640625 -3.28125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-3"> +<path style="stroke:none;" d="M 2.53125 -6.375 L 1.359375 -6.375 L 1.359375 -5.203125 L 2.53125 -5.203125 Z M 1.359375 -1.15625 L 1.359375 0 L 2.53125 0 L 2.53125 -1.15625 Z M 1.359375 -1.15625 "/> +</symbol> +<symbol overflow="visible" id="glyph1-4"> +<path style="stroke:none;" d="M 2.1875 -9.953125 L 1.125 -9.953125 L 1.125 0 L 2.203125 0 L 2.203125 -0.640625 C 2.875 -0.015625 3.578125 0.140625 4.078125 0.140625 C 5.4375 0.140625 6.6875 -1.25 6.6875 -3.203125 C 6.6875 -4.96875 5.734375 -6.515625 4.40625 -6.515625 C 3.984375 -6.515625 3.0625 -6.421875 2.1875 -5.703125 Z M 2.203125 -4.828125 C 2.46875 -5.234375 2.984375 -5.65625 3.6875 -5.65625 C 4.5625 -5.65625 5.59375 -4.984375 5.59375 -3.203125 C 5.59375 -1.328125 4.421875 -0.71875 3.546875 -0.71875 C 3.140625 -0.71875 2.875 -0.859375 2.609375 -1.0625 C 2.265625 -1.359375 2.203125 -1.625 2.203125 -1.859375 Z M 2.203125 -4.828125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-5"> +<path style="stroke:none;" d="M 2.1875 -3.140625 C 2.1875 -4.59375 3.265625 -5.53125 4.5625 -5.546875 L 4.5625 -6.515625 C 3.25 -6.5 2.5 -5.734375 2.109375 -5.171875 L 2.109375 -6.4375 L 1.125 -6.4375 L 1.125 0 L 2.1875 0 Z M 2.1875 -3.140625 "/> +</symbol> +<symbol overflow="visible" id="glyph1-6"> +<path style="stroke:none;" d="M 2.265625 -9.734375 L 1.03125 -9.734375 L 1.03125 -8.5 L 2.265625 -8.5 Z M 2.1875 -6.375 L 1.125 -6.375 L 1.125 0 L 2.1875 0 Z M 2.1875 -6.375 "/> +</symbol> +<symbol overflow="visible" id="glyph1-7"> +<path style="stroke:none;" d="M 6.0625 -9.953125 L 5 -9.953125 L 5 -5.765625 C 4.34375 -6.3125 3.59375 -6.515625 2.984375 -6.515625 C 1.625 -6.515625 0.5 -5.046875 0.5 -3.1875 C 0.5 -1.328125 1.5625 0.140625 2.921875 0.140625 C 3.453125 0.140625 4.265625 -0.03125 4.984375 -0.734375 L 4.984375 0 L 6.0625 0 Z M 4.984375 -1.6875 C 4.640625 -1.078125 4.125 -0.71875 3.5 -0.71875 C 2.625 -0.71875 1.59375 -1.390625 1.59375 -3.171875 C 1.59375 -5.078125 2.8125 -5.65625 3.640625 -5.65625 C 4.203125 -5.65625 4.65625 -5.359375 4.984375 -4.890625 Z M 4.984375 -1.6875 "/> +</symbol> +<symbol overflow="visible" id="glyph1-8"> +<path style="stroke:none;" d="M 4.890625 -5.65625 C 4.890625 -5.65625 4.921875 -5.625 4.9375 -5.59375 C 5.234375 -5.625 5.546875 -5.671875 6.078125 -5.671875 C 6.125 -5.671875 6.453125 -5.671875 6.8125 -5.640625 L 6.65625 -6.515625 C 6.390625 -6.515625 5.40625 -6.5 4.453125 -6.03125 C 3.984375 -6.4375 3.40625 -6.515625 3.125 -6.515625 C 1.875 -6.515625 0.875 -5.46875 0.875 -4.203125 C 0.875 -3.6875 1.03125 -3.21875 1.34375 -2.78125 C 1.015625 -2.328125 0.9375 -1.890625 0.9375 -1.546875 C 0.9375 -1.015625 1.140625 -0.65625 1.296875 -0.46875 C 0.5625 0 0.390625 0.609375 0.390625 1.015625 C 0.390625 2.0625 1.75 2.9375 3.5 2.9375 C 5.25 2.9375 6.625 2.09375 6.625 1 C 6.625 -1 4.296875 -1 3.71875 -1 L 2.5 -1 C 2.296875 -1 1.671875 -1 1.671875 -1.765625 C 1.671875 -2.078125 1.734375 -2.171875 1.828125 -2.296875 C 2.0625 -2.125 2.53125 -1.875 3.109375 -1.875 C 4.34375 -1.875 5.359375 -2.890625 5.359375 -4.203125 C 5.359375 -4.71875 5.171875 -5.25 4.875 -5.640625 Z M 3.125 -2.671875 C 2.5 -2.671875 1.859375 -3.09375 1.859375 -4.1875 C 1.859375 -5.46875 2.671875 -5.71875 3.109375 -5.71875 C 3.75 -5.71875 4.375 -5.296875 4.375 -4.203125 C 4.375 -2.921875 3.578125 -2.671875 3.125 -2.671875 Z M 3.734375 0.03125 C 4.046875 0.03125 5.625 0.03125 5.625 1.015625 C 5.625 1.671875 4.640625 2.15625 3.515625 2.15625 C 2.390625 2.15625 1.390625 1.703125 1.390625 1 C 1.390625 0.96875 1.390625 0.03125 2.484375 0.03125 Z M 3.734375 0.03125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-9"> +<path style="stroke:none;" d="M 5.84375 -3.234375 C 5.84375 -3.84375 5.78125 -4.71875 5.328125 -5.484375 C 4.734375 -6.46875 3.734375 -6.578125 3.3125 -6.578125 C 1.765625 -6.578125 0.46875 -5.09375 0.46875 -3.234375 C 0.46875 -1.328125 1.84375 0.140625 3.515625 0.140625 C 4.171875 0.140625 4.96875 -0.046875 5.75 -0.609375 C 5.75 -0.671875 5.703125 -1.125 5.703125 -1.140625 C 5.6875 -1.15625 5.671875 -1.484375 5.671875 -1.53125 C 4.8125 -0.8125 3.96875 -0.71875 3.546875 -0.71875 C 2.4375 -0.71875 1.484375 -1.703125 1.46875 -3.234375 Z M 1.546875 -4 C 1.796875 -4.96875 2.46875 -5.71875 3.3125 -5.71875 C 3.765625 -5.71875 4.75 -5.515625 4.984375 -4 Z M 1.546875 -4 "/> +</symbol> +<symbol overflow="visible" id="glyph1-10"> +<path style="stroke:none;" d="M 10 -4.3125 C 10 -5.3125 9.734375 -6.515625 8.0625 -6.515625 C 6.84375 -6.515625 6.171875 -5.671875 5.953125 -5.34375 C 5.6875 -6.25 4.90625 -6.515625 4.15625 -6.515625 C 2.984375 -6.515625 2.359375 -5.75 2.125 -5.453125 L 2.125 -6.4375 L 1.109375 -6.4375 L 1.109375 0 L 2.1875 0 L 2.1875 -3.578125 C 2.1875 -4.515625 2.5625 -5.65625 3.609375 -5.65625 C 4.9375 -5.65625 5 -4.75 5 -4.21875 L 5 0 L 6.09375 0 L 6.09375 -3.578125 C 6.09375 -4.515625 6.46875 -5.65625 7.515625 -5.65625 C 8.828125 -5.65625 8.90625 -4.75 8.90625 -4.21875 L 8.90625 0 L 10 0 Z M 10 -4.3125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-11"> +<path style="stroke:none;" d="M 6.578125 -3.15625 C 6.578125 -5.09375 5.15625 -6.578125 3.515625 -6.578125 C 1.828125 -6.578125 0.4375 -5.0625 0.4375 -3.15625 C 0.4375 -1.28125 1.859375 0.140625 3.5 0.140625 C 5.1875 0.140625 6.578125 -1.3125 6.578125 -3.15625 Z M 3.515625 -0.75 C 2.484375 -0.75 1.515625 -1.609375 1.515625 -3.296875 C 1.515625 -5.03125 2.59375 -5.71875 3.5 -5.71875 C 4.484375 -5.71875 5.5 -4.984375 5.5 -3.296875 C 5.5 -1.53125 4.46875 -0.75 3.515625 -0.75 Z M 3.515625 -0.75 "/> +</symbol> +<symbol overflow="visible" id="glyph1-12"> +<path style="stroke:none;" d="M 4.8125 -6.140625 C 3.90625 -6.5625 3.125 -6.578125 2.796875 -6.578125 C 2.46875 -6.578125 0.46875 -6.578125 0.46875 -4.71875 C 0.46875 -4.09375 0.8125 -3.65625 1.03125 -3.453125 C 1.546875 -3.015625 1.90625 -2.9375 2.75 -2.765625 C 3.234375 -2.671875 4.0625 -2.5 4.0625 -1.734375 C 4.0625 -0.75 2.9375 -0.75 2.734375 -0.75 C 2.171875 -0.75 1.328125 -0.90625 0.5625 -1.46875 L 0.390625 -0.484375 C 0.453125 -0.4375 1.4375 0.140625 2.75 0.140625 C 4.609375 0.140625 5.046875 -0.96875 5.046875 -1.828125 C 5.046875 -2.546875 4.609375 -3.015625 4.546875 -3.078125 C 4.015625 -3.625 3.578125 -3.71875 2.71875 -3.890625 C 2.1875 -3.984375 1.46875 -4.125 1.46875 -4.84375 C 1.46875 -5.734375 2.46875 -5.734375 2.65625 -5.734375 C 3.40625 -5.734375 4.015625 -5.5625 4.640625 -5.203125 Z M 4.8125 -6.140625 "/> +</symbol> +<symbol overflow="visible" id="glyph1-13"> +<path style="stroke:none;" d="M 2.203125 -0.640625 C 2.703125 -0.203125 3.296875 0.140625 4.078125 0.140625 C 5.453125 0.140625 6.6875 -1.25 6.6875 -3.203125 C 6.6875 -4.9375 5.765625 -6.515625 4.4375 -6.515625 C 3.84375 -6.515625 2.921875 -6.328125 2.1875 -5.6875 L 2.1875 -6.375 L 1.125 -6.375 L 1.125 2.78125 L 2.203125 2.78125 Z M 2.203125 -4.8125 C 2.53125 -5.3125 3.078125 -5.625 3.671875 -5.625 C 4.734375 -5.625 5.59375 -4.546875 5.59375 -3.1875 C 5.59375 -1.75 4.609375 -0.71875 3.546875 -0.71875 C 3.140625 -0.71875 2.875 -0.859375 2.609375 -1.0625 C 2.25 -1.375 2.203125 -1.640625 2.203125 -1.859375 Z M 2.203125 -4.8125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-14"> +<path style="stroke:none;" d="M 2.453125 -5.53125 L 4.4375 -5.53125 L 4.4375 -6.375 L 2.453125 -6.375 L 2.453125 -8.1875 L 1.46875 -8.1875 L 1.46875 -6.375 L 0.265625 -6.375 L 0.265625 -5.53125 L 1.4375 -5.53125 L 1.4375 -1.671875 C 1.4375 -0.84375 1.625 0.140625 2.609375 0.140625 C 3.578125 0.140625 4.234375 -0.1875 4.671875 -0.421875 L 4.453125 -1.25 C 3.953125 -0.796875 3.421875 -0.75 3.171875 -0.75 C 2.53125 -0.75 2.453125 -1.421875 2.453125 -1.921875 Z M 2.453125 -5.53125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-15"> +<path style="stroke:none;" d="M 6.078125 -4.3125 C 6.078125 -5.1875 5.890625 -6.515625 4.15625 -6.515625 C 3.359375 -6.515625 2.671875 -6.15625 2.125 -5.46875 L 2.125 -6.4375 L 1.109375 -6.4375 L 1.109375 0 L 2.1875 0 L 2.1875 -3.578125 C 2.1875 -4.453125 2.53125 -5.65625 3.609375 -5.65625 C 4.953125 -5.65625 4.984375 -4.71875 4.984375 -4.21875 L 4.984375 0 L 6.078125 0 Z M 6.078125 -4.3125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-16"> +<path style="stroke:none;" d="M 2.484375 -5.53125 L 4.015625 -5.53125 L 4.015625 -6.375 L 2.453125 -6.375 L 2.453125 -8.09375 C 2.453125 -9.0625 3.265625 -9.234375 3.75 -9.234375 C 4.25 -9.234375 4.6875 -9.078125 4.859375 -9.015625 L 4.859375 -9.953125 C 4.765625 -9.984375 4.28125 -10.09375 3.765625 -10.09375 C 2.390625 -10.09375 1.421875 -9.046875 1.421875 -7.65625 L 1.421875 -6.375 L 0.375 -6.375 L 0.375 -5.53125 L 1.421875 -5.53125 L 1.421875 0 L 2.484375 0 Z M 2.484375 -5.53125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-17"> +<path style="stroke:none;" d="M 6.078125 -6.375 L 4.984375 -6.375 L 4.984375 -2.265625 C 4.984375 -1.171875 4.234375 -0.640625 3.296875 -0.640625 C 2.296875 -0.640625 2.1875 -1.015625 2.1875 -1.65625 L 2.1875 -6.375 L 1.109375 -6.375 L 1.109375 -1.59375 C 1.109375 -0.5625 1.4375 0.140625 2.609375 0.140625 C 3.015625 0.140625 4.140625 0.078125 5.015625 -0.71875 L 5.015625 0 L 6.078125 0 Z M 6.078125 -6.375 "/> +</symbol> +<symbol overflow="visible" id="glyph1-18"> +<path style="stroke:none;" d="M 5.609375 -4.203125 C 5.609375 -5.578125 4.625 -6.578125 3.28125 -6.578125 C 2.421875 -6.578125 1.78125 -6.390625 1.078125 -5.984375 L 1.15625 -5.03125 C 1.796875 -5.5 2.453125 -5.75 3.28125 -5.75 C 3.9375 -5.75 4.515625 -5.21875 4.515625 -4.171875 L 4.515625 -3.578125 C 3.875 -3.5625 3.015625 -3.515625 2.15625 -3.234375 C 1.1875 -2.890625 0.625 -2.359375 0.625 -1.65625 C 0.625 -1.015625 1 0.140625 2.21875 0.140625 C 3.015625 0.140625 4.015625 -0.09375 4.546875 -0.53125 L 4.546875 0 L 5.609375 0 Z M 4.515625 -1.921875 C 4.515625 -1.640625 4.515625 -1.296875 4.046875 -1 C 3.65625 -0.765625 3.171875 -0.71875 2.953125 -0.71875 C 2.1875 -0.71875 1.65625 -1.140625 1.65625 -1.65625 C 1.65625 -2.640625 3.640625 -2.859375 4.515625 -2.859375 Z M 4.515625 -1.921875 "/> +</symbol> +<symbol overflow="visible" id="glyph1-19"> +<path style="stroke:none;" d="M 6.203125 -6.375 L 5.140625 -6.375 C 4.46875 -4.671875 3.375 -1.859375 3.3125 -0.828125 L 3.296875 -0.828125 C 3.234375 -1.671875 2.46875 -3.578125 2.359375 -3.859375 L 1.328125 -6.375 L 0.203125 -6.375 L 2.875 0 L 2.359375 1.3125 C 2.046875 2.015625 1.84375 2.09375 1.578125 2.09375 C 1.375 2.09375 0.921875 2.046875 0.46875 1.875 L 0.5625 2.8125 C 0.640625 2.828125 1.125 2.921875 1.578125 2.921875 C 1.921875 2.921875 2.59375 2.921875 3.21875 1.34375 Z M 6.203125 -6.375 "/> +</symbol> +<symbol overflow="visible" id="glyph1-20"> +<path style="stroke:none;" d="M 5.84375 -4.671875 C 7.40625 -5.125 8.25 -6.203125 8.25 -7.265625 C 8.25 -8.703125 6.71875 -9.953125 4.6875 -9.953125 L 1.3125 -9.953125 L 1.3125 0 L 2.515625 0 L 2.515625 -4.546875 L 4.75 -4.546875 L 7.40625 0 L 8.640625 0 Z M 2.515625 -5.40625 L 2.515625 -9.15625 L 4.53125 -9.15625 C 6.265625 -9.15625 7.109375 -8.234375 7.109375 -7.265625 C 7.109375 -6.390625 6.34375 -5.40625 4.53125 -5.40625 Z M 2.515625 -5.40625 "/> +</symbol> +<symbol overflow="visible" id="glyph1-21"> +<path style="stroke:none;" d="M 8.171875 -1.65625 C 7.296875 -1 6.703125 -0.765625 5.453125 -0.765625 C 3.578125 -0.765625 2.171875 -2.703125 2.171875 -5 C 2.171875 -6.9375 3.328125 -9.21875 5.515625 -9.21875 C 6.453125 -9.21875 7.171875 -8.9375 7.890625 -8.453125 L 8.109375 -9.625 C 7.171875 -9.984375 6.46875 -10.109375 5.484375 -10.109375 C 3.046875 -10.109375 0.953125 -7.953125 0.953125 -4.984375 C 0.953125 -1.84375 3.25 0.125 5.34375 0.125 C 6.78125 0.125 7.09375 0.046875 8.265625 -0.65625 Z M 8.171875 -1.65625 "/> +</symbol> +<symbol overflow="visible" id="glyph1-22"> +<path style="stroke:none;" d="M 3 -9.953125 L 1.359375 -9.953125 L 1.359375 0 L 2.46875 0 L 2.46875 -8.84375 L 2.484375 -8.84375 C 2.6875 -7.875 5 -1.734375 5.546875 -0.296875 L 6.59375 -0.296875 C 7.078125 -1.53125 9.4375 -7.78125 9.703125 -8.859375 L 9.703125 0 L 10.8125 0 L 10.8125 -9.953125 L 9.1875 -9.953125 L 7.546875 -5.53125 C 6.796875 -3.53125 6.234375 -2.015625 6.09375 -1.359375 L 6.078125 -1.359375 C 6.03125 -1.609375 5.859375 -2.140625 5.671875 -2.703125 C 5.40625 -3.46875 5.40625 -3.5 5.171875 -4.09375 Z M 3 -9.953125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-23"> +<path style="stroke:none;" d="M 8.53125 -9.953125 L 7.296875 -9.953125 L 7.296875 -5.609375 L 2.53125 -5.609375 L 2.53125 -9.953125 L 1.296875 -9.953125 L 1.296875 0 L 2.53125 0 L 2.53125 -4.75 L 7.296875 -4.75 L 7.296875 0 L 8.53125 0 Z M 8.53125 -9.953125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-24"> +<path style="stroke:none;" d="M 5.265625 -9.953125 L 4 -9.953125 L 0.390625 0 L 1.453125 0 L 2.5 -2.90625 L 6.546875 -2.90625 L 7.609375 0 L 8.875 0 Z M 4.515625 -8.921875 L 6.234375 -3.71875 L 2.8125 -3.71875 Z M 4.515625 -8.921875 "/> +</symbol> +<symbol overflow="visible" id="glyph1-25"> +<path style="stroke:none;" d="M 1.328125 -9.953125 L 1.328125 0 L 5.03125 0 C 7.0625 0 8.53125 -1.296875 8.53125 -2.703125 C 8.53125 -3.953125 7.28125 -4.984375 5.8125 -5.203125 C 7.484375 -5.671875 8.140625 -6.625 8.140625 -7.453125 C 8.140625 -8.75 6.671875 -9.953125 4.640625 -9.953125 Z M 2.5 -5.609375 L 2.5 -9.15625 L 4.265625 -9.15625 C 5.796875 -9.15625 7.03125 -8.390625 7.03125 -7.4375 C 7.03125 -6.4375 5.796875 -5.609375 4.28125 -5.609375 Z M 2.5 -0.796875 L 2.5 -4.75 L 4.40625 -4.75 C 6.25 -4.75 7.40625 -3.71875 7.40625 -2.71875 C 7.40625 -1.703125 6.234375 -0.796875 4.640625 -0.796875 Z M 2.5 -0.796875 "/> +</symbol> +<symbol overflow="visible" id="glyph1-26"> +<path style="stroke:none;" d="M 2.53125 -9.953125 L 1.296875 -9.953125 L 1.296875 0 L 2.53125 0 Z M 2.53125 -9.953125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-27"> +<path style="stroke:none;" d="M 6.53125 -9.546875 C 5.9375 -9.875 5.21875 -10.25 3.9375 -10.25 C 2.015625 -10.25 0.78125 -8.875 0.78125 -7.4375 C 0.78125 -6.421875 1.390625 -5.765625 1.46875 -5.6875 C 2.171875 -4.984375 2.65625 -4.84375 3.578125 -4.625 C 4.796875 -4.3125 4.984375 -4.265625 5.453125 -3.78125 C 5.6875 -3.53125 5.90625 -3.0625 5.90625 -2.5625 C 5.90625 -1.578125 5.09375 -0.65625 3.859375 -0.65625 C 2.8125 -0.65625 1.6875 -1.078125 0.84375 -1.84375 L 0.625 -0.6875 C 1.9375 0.171875 3.203125 0.296875 3.859375 0.296875 C 5.703125 0.296875 7.015625 -1.125 7.015625 -2.71875 C 7.015625 -3.625 6.5625 -4.3125 6.25 -4.671875 C 5.59375 -5.375 5.0625 -5.515625 4.109375 -5.765625 C 3.125 -6.015625 2.765625 -6.09375 2.453125 -6.390625 C 2.265625 -6.59375 1.875 -6.953125 1.875 -7.609375 C 1.875 -8.484375 2.671875 -9.328125 3.9375 -9.328125 C 5.15625 -9.328125 5.796875 -8.84375 6.3125 -8.390625 Z M 6.53125 -9.546875 "/> +</symbol> +<symbol overflow="visible" id="glyph1-28"> +<path style="stroke:none;" d="M 6.078125 -4.3125 C 6.078125 -5.1875 5.890625 -6.515625 4.15625 -6.515625 C 3.171875 -6.515625 2.515625 -5.953125 2.171875 -5.515625 L 2.171875 -9.953125 L 1.109375 -9.953125 L 1.109375 0 L 2.1875 0 L 2.1875 -3.578125 C 2.1875 -4.453125 2.53125 -5.65625 3.609375 -5.65625 C 4.953125 -5.65625 4.984375 -4.71875 4.984375 -4.21875 L 4.984375 0 L 6.078125 0 Z M 6.078125 -4.3125 "/> +</symbol> +<symbol overflow="visible" id="glyph1-29"> +<path style="stroke:none;" d="M 9.328125 -6.375 L 8.28125 -6.375 L 7.421875 -3.453125 C 7.21875 -2.765625 6.8125 -1.421875 6.75 -0.796875 L 6.734375 -0.796875 C 6.703125 -1.140625 6.46875 -2.109375 6.171875 -3.125 L 5.21875 -6.375 L 4.234375 -6.375 L 3.40625 -3.5625 C 3.15625 -2.671875 2.8125 -1.4375 2.765625 -0.828125 L 2.75 -0.828125 C 2.734375 -1.109375 2.578125 -1.859375 2.3125 -2.828125 L 1.296875 -6.375 L 0.203125 -6.375 L 2.125 0 L 3.234375 0 C 3.765625 -1.8125 4.609375 -4.53125 4.6875 -5.53125 L 4.703125 -5.53125 C 4.734375 -4.953125 5.015625 -3.921875 5.125 -3.578125 L 6.140625 0 L 7.40625 0 Z M 9.328125 -6.375 "/> +</symbol> +<symbol overflow="visible" id="glyph1-30"> +<path style="stroke:none;" d="M 4.8125 -4.140625 C 6.78125 -4.140625 8.140625 -5.5625 8.140625 -7.0625 C 8.140625 -8.578125 6.75 -9.953125 4.8125 -9.953125 L 1.3125 -9.953125 L 1.3125 0 L 2.53125 0 L 2.53125 -4.140625 Z M 4.5 -9.15625 C 6.1875 -9.15625 7.015625 -8.140625 7.015625 -7.078125 C 7.015625 -5.9375 6.140625 -4.984375 4.5 -4.984375 L 2.515625 -4.984375 L 2.515625 -9.15625 Z M 4.5 -9.15625 "/> +</symbol> +</g> +<clipPath id="clip1"> + <path d="M 0 0 L 541.902344 0 L 541.902344 142.285156 L 0 142.285156 Z M 0 0 "/> +</clipPath> +<clipPath id="clip2"> + <path d="M 102 92 L 245 92 L 245 142.285156 L 102 142.285156 Z M 102 92 "/> +</clipPath> +<clipPath id="clip3"> + <path d="M 302 92 L 442 92 L 442 142.285156 L 302 142.285156 Z M 302 92 "/> +</clipPath> +<clipPath id="clip4"> + <path d="M 17 101 L 67 101 L 67 142.285156 L 17 142.285156 Z M 17 101 "/> +</clipPath> +<clipPath id="clip5"> + <path d="M 92 101 L 142 101 L 142 142.285156 L 92 142.285156 Z M 92 101 "/> +</clipPath> +<clipPath id="clip6"> + <path d="M 205 101 L 255 101 L 255 142.285156 L 205 142.285156 Z M 205 101 "/> +</clipPath> +<clipPath id="clip7"> + <path d="M 292 101 L 342 101 L 342 142.285156 L 292 142.285156 Z M 292 101 "/> +</clipPath> +<clipPath id="clip8"> + <path d="M 402 101 L 452 101 L 452 142.285156 L 402 142.285156 Z M 402 101 "/> +</clipPath> +<clipPath id="clip9"> + <path d="M 479 101 L 528 101 L 528 142.285156 L 479 142.285156 Z M 479 101 "/> +</clipPath> +</defs> +<g id="surface1"> +<g clip-path="url(#clip1)" clip-rule="nonzero"> +<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 0 142.285156 L 543.933594 142.285156 L 543.933594 -0.535156 L 0 -0.535156 Z M 0 142.285156 "/> +</g> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 93.618469 13.681906 L -93.619813 13.681906 C -96.369813 13.681906 -98.600281 11.451438 -98.600281 8.701438 L -98.600281 -17.204812 C -98.600281 -19.954812 -96.369813 -22.185281 -93.619813 -22.185281 L 93.618469 -22.185281 C 96.368469 -22.185281 98.598937 -19.954812 98.598937 -17.204812 L 98.598937 8.701438 C 98.598937 11.451438 96.368469 13.681906 93.618469 13.681906 Z M 93.618469 13.681906 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph0-1" x="215.699" y="15.293"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph0-2" x="222.091667" y="15.293"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-1" x="229.467" y="15.293"/> + <use xlink:href="#glyph1-2" x="235.710466" y="15.293"/> + <use xlink:href="#glyph1-2" x="242.136129" y="15.293"/> + <use xlink:href="#glyph1-3" x="248.561792" y="15.293"/> + <use xlink:href="#glyph1-3" x="252.463959" y="15.293"/> + <use xlink:href="#glyph1-4" x="256.366125" y="15.293"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-5" x="263.184874" y="15.293"/> + <use xlink:href="#glyph1-6" x="267.959289" y="15.293"/> + <use xlink:href="#glyph1-7" x="271.263219" y="15.293"/> + <use xlink:href="#glyph1-8" x="278.469315" y="15.293"/> + <use xlink:href="#glyph1-9" x="285.493215" y="15.293"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph0-3" x="291.733" y="15.293"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-10" x="303.797" y="15.293"/> + <use xlink:href="#glyph1-11" x="314.905263" y="15.293"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-7" x="322.31651" y="15.293"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-7" x="203.901" y="29.24"/> + <use xlink:href="#glyph1-9" x="211.107096" y="29.24"/> + <use xlink:href="#glyph1-12" x="217.350563" y="29.24"/> + <use xlink:href="#glyph1-1" x="222.734691" y="29.24"/> + <use xlink:href="#glyph1-5" x="228.978158" y="29.24"/> + <use xlink:href="#glyph1-6" x="233.752573" y="29.24"/> + <use xlink:href="#glyph1-13" x="237.056503" y="29.24"/> + <use xlink:href="#glyph1-14" x="244.262599" y="29.24"/> + <use xlink:href="#glyph1-6" x="249.335415" y="29.24"/> + <use xlink:href="#glyph1-11" x="252.639345" y="29.24"/> + <use xlink:href="#glyph1-15" x="259.663245" y="29.24"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-11" x="271.546202" y="29.24"/> + <use xlink:href="#glyph1-16" x="278.570102" y="29.24"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-4" x="287.553692" y="29.24"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-11" x="295.147136" y="29.24"/> + <use xlink:href="#glyph1-17" x="302.171035" y="29.24"/> + <use xlink:href="#glyph1-15" x="309.377132" y="29.24"/> + <use xlink:href="#glyph1-7" x="316.583228" y="29.24"/> + <use xlink:href="#glyph1-18" x="323.789324" y="29.24"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-5" x="330.126041" y="29.24"/> + <use xlink:href="#glyph1-19" x="334.900456" y="29.24"/> +</g> +<g clip-path="url(#clip2)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -53.619813 -99.095437 L -144.807313 -99.095437 C -147.006531 -99.095437 -148.791688 -100.880594 -148.791688 -103.079812 L -148.791688 -118.025125 C -148.791688 -120.22825 -147.006531 -122.0095 -144.807313 -122.0095 L -53.619813 -122.0095 C -51.420594 -122.0095 -49.635438 -120.22825 -49.635438 -118.025125 L -49.635438 -103.079812 C -49.635438 -100.880594 -51.420594 -99.095437 -53.619813 -99.095437 Z M -53.619813 -99.095437 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-20" x="133.785" y="129.463"/> + <use xlink:href="#glyph1-17" x="142.825975" y="129.463"/> + <use xlink:href="#glyph1-12" x="150.032072" y="129.463"/> + <use xlink:href="#glyph1-14" x="155.4162" y="129.463"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-4" x="165.165878" y="129.463"/> + <use xlink:href="#glyph1-6" x="172.371974" y="129.463"/> + <use xlink:href="#glyph1-15" x="175.675904" y="129.463"/> + <use xlink:href="#glyph1-7" x="182.882" y="129.463"/> + <use xlink:href="#glyph1-6" x="190.088097" y="129.463"/> + <use xlink:href="#glyph1-15" x="193.392026" y="129.463"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-8" x="200.612469" y="129.463"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-12" x="207.622022" y="129.463"/> +</g> +<g clip-path="url(#clip3)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 143.3255 -99.095437 L 55.102844 -99.095437 C 52.903625 -99.095437 51.118469 -100.880594 51.118469 -103.079812 L 51.118469 -118.025125 C 51.118469 -120.22825 52.903625 -122.0095 55.102844 -122.0095 L 143.3255 -122.0095 C 145.524719 -122.0095 147.309875 -120.22825 147.309875 -118.025125 L 147.309875 -103.079812 C 147.309875 -100.880594 145.524719 -99.095437 143.3255 -99.095437 Z M 143.3255 -99.095437 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-21" x="333.693" y="129.463"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph0-4" x="342.668" y="129.463"/> + <use xlink:href="#glyph0-4" x="350.050555" y="129.463"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-4" x="362.115" y="129.463"/> + <use xlink:href="#glyph1-6" x="369.321096" y="129.463"/> + <use xlink:href="#glyph1-15" x="372.625026" y="129.463"/> + <use xlink:href="#glyph1-7" x="379.831122" y="129.463"/> + <use xlink:href="#glyph1-6" x="387.037219" y="129.463"/> + <use xlink:href="#glyph1-15" x="390.341148" y="129.463"/> + <use xlink:href="#glyph1-8" x="397.547245" y="129.463"/> + <use xlink:href="#glyph1-12" x="404.571144" y="129.463"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-20" x="4.343" y="126.574"/> + <use xlink:href="#glyph1-17" x="13.383975" y="126.574"/> + <use xlink:href="#glyph1-12" x="20.590072" y="126.574"/> + <use xlink:href="#glyph1-14" x="25.9742" y="126.574"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-1" x="3.941" y="140.522"/> + <use xlink:href="#glyph1-11" x="10.184466" y="140.522"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-7" x="17.595713" y="140.522"/> + <use xlink:href="#glyph1-9" x="24.801809" y="140.522"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-21" x="514.177" y="126.574"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph0-4" x="523.151" y="126.574"/> + <use xlink:href="#glyph0-4" x="530.533555" y="126.574"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-1" x="514.177" y="140.522"/> + <use xlink:href="#glyph1-11" x="520.420466" y="140.522"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-7" x="527.831713" y="140.522"/> + <use xlink:href="#glyph1-9" x="535.037809" y="140.522"/> +</g> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0.00128125 -22.931375 L 0.00128125 -68.032937 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -99.213563 -89.1345 L -99.213563 -68.032937 L 99.212219 -68.032937 L 99.212219 -89.1345 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +<path style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.317146 0.0002575 C 5.539802 0.207289 2.129646 1.371351 0.00074 2.640882 L 0.00074 -2.640368 C 2.129646 -1.370836 5.539802 -0.206774 6.317146 0.0002575 Z M 6.317146 0.0002575 " transform="matrix(0,1,1,0,173.39818,103.56176)"/> +<path style="fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.317146 -0.00160125 C 5.539802 0.20543 2.129646 1.373399 0.00074 2.639024 L 0.00074 -2.63832 C 2.129646 -1.372695 5.539802 -0.204726 6.317146 -0.00160125 Z M 6.317146 -0.00160125 " transform="matrix(0,1,1,0,371.82582,103.56176)"/> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M -227.619813 -110.552469 L -158.752625 -110.552469 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 38.675781 124.980469 C 39.453125 125.1875 42.859375 126.351562 44.992188 127.621094 L 44.992188 122.339844 C 42.859375 123.609375 39.453125 124.777344 38.675781 124.980469 Z M 38.675781 124.980469 "/> +<g clip-path="url(#clip4)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.316149 -0.00123125 C 5.538805 0.2058 2.132555 1.369862 -0.0002575 2.639394 L -0.0002575 -2.641856 C 2.132555 -1.372325 5.538805 -0.204356 6.316149 -0.00123125 Z M 6.316149 -0.00123125 " transform="matrix(-1,0,0,1,44.99193,124.9817)"/> +</g> +<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 120.171875 124.980469 C 119.398438 124.777344 115.988281 123.609375 113.859375 122.339844 L 113.859375 127.621094 C 115.988281 126.351562 119.398438 125.1875 120.171875 124.980469 Z M 120.171875 124.980469 "/> +<g clip-path="url(#clip5)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.313975 0.00123125 C 5.540537 0.204356 2.130381 1.372325 0.001475 2.641856 L 0.001475 -2.639394 C 2.130381 -1.369862 5.540537 -0.2058 6.313975 0.00123125 Z M 6.313975 0.00123125 " transform="matrix(1,0,0,-1,113.8579,124.9817)"/> +</g> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:7.97021,5.97766;stroke-miterlimit:10;" d="M -39.6745 -110.552469 L 41.157531 -110.552469 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 226.621094 124.980469 C 227.398438 125.1875 230.808594 126.351562 232.9375 127.621094 L 232.9375 122.339844 C 230.808594 123.609375 227.398438 124.777344 226.621094 124.980469 Z M 226.621094 124.980469 "/> +<g clip-path="url(#clip6)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.317366 -0.00123125 C 5.540023 0.2058 2.129866 1.369862 0.00096 2.639394 L 0.00096 -2.641856 C 2.129866 -1.372325 5.540023 -0.204356 6.317366 -0.00123125 Z M 6.317366 -0.00123125 " transform="matrix(-1,0,0,1,232.93846,124.9817)"/> +</g> +<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 320.082031 124.980469 C 319.308594 124.777344 315.898438 123.609375 313.769531 122.339844 L 313.769531 127.621094 C 315.898438 126.351562 319.308594 125.1875 320.082031 124.980469 Z M 320.082031 124.980469 "/> +<g clip-path="url(#clip7)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.313811 0.00123125 C 5.540374 0.204356 2.130217 1.372325 0.00131125 2.641856 L 0.00131125 -2.639394 C 2.130217 -1.369862 5.540374 -0.2058 6.313811 0.00123125 Z M 6.313811 0.00123125 " transform="matrix(1,0,0,-1,313.76822,124.9817)"/> +</g> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 157.270812 -110.552469 L 227.618469 -110.552469 " transform="matrix(1,0,0,-1,272.612,14.428)"/> +<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 423.566406 124.980469 C 424.34375 125.1875 427.753906 126.351562 429.882812 127.621094 L 429.882812 122.339844 C 427.753906 123.609375 424.34375 124.777344 423.566406 124.980469 Z M 423.566406 124.980469 "/> +<g clip-path="url(#clip8)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.317014 -0.00123125 C 5.53967 0.2058 2.129514 1.369862 0.0006075 2.639394 L 0.0006075 -2.641856 C 2.129514 -1.372325 5.53967 -0.204356 6.317014 -0.00123125 Z M 6.317014 -0.00123125 " transform="matrix(-1,0,0,1,429.88342,124.9817)"/> +</g> +<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 506.546875 124.980469 C 505.773438 124.777344 502.363281 123.609375 500.230469 122.339844 L 500.230469 127.621094 C 502.363281 126.351562 505.773438 125.1875 506.546875 124.980469 Z M 506.546875 124.980469 "/> +<g clip-path="url(#clip9)" clip-rule="nonzero"> +<path style="fill:none;stroke-width:1.49442;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 6.314805 0.00123125 C 5.541367 0.204356 2.131211 1.372325 -0.00160125 2.641856 L -0.00160125 -2.639394 C 2.131211 -1.369862 5.541367 -0.2058 6.314805 0.00123125 Z M 6.314805 0.00123125 " transform="matrix(1,0,0,-1,500.23207,124.9817)"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-22" x="148.925" y="75.603"/> + <use xlink:href="#glyph1-18" x="161.112097" y="75.603"/> + <use xlink:href="#glyph1-1" x="167.836161" y="75.603"/> + <use xlink:href="#glyph1-5" x="174.079627" y="75.603"/> + <use xlink:href="#glyph1-11" x="178.854042" y="75.603"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-9" x="190.554803" y="75.603"/> + <use xlink:href="#glyph1-2" x="196.798269" y="75.603"/> + <use xlink:href="#glyph1-13" x="203.223932" y="75.603"/> + <use xlink:href="#glyph1-18" x="210.430029" y="75.603"/> + <use xlink:href="#glyph1-15" x="217.154093" y="75.603"/> + <use xlink:href="#glyph1-12" x="224.360189" y="75.603"/> + <use xlink:href="#glyph1-6" x="229.744318" y="75.603"/> + <use xlink:href="#glyph1-11" x="233.048248" y="75.603"/> + <use xlink:href="#glyph1-15" x="240.072147" y="75.603"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-21" x="297.94" y="75.603"/> + <use xlink:href="#glyph1-11" x="306.914983" y="75.603"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-7" x="314.32623" y="75.603"/> + <use xlink:href="#glyph1-9" x="321.532326" y="75.603"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-8" x="332.452653" y="75.603"/> + <use xlink:href="#glyph1-9" x="339.476553" y="75.603"/> + <use xlink:href="#glyph1-15" x="345.720019" y="75.603"/> + <use xlink:href="#glyph1-9" x="352.926115" y="75.603"/> + <use xlink:href="#glyph1-5" x="359.169582" y="75.603"/> + <use xlink:href="#glyph1-18" x="363.943997" y="75.603"/> + <use xlink:href="#glyph1-14" x="370.668061" y="75.603"/> + <use xlink:href="#glyph1-6" x="375.740877" y="75.603"/> + <use xlink:href="#glyph1-11" x="379.044807" y="75.603"/> + <use xlink:href="#glyph1-15" x="386.068707" y="75.603"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-23" x="231.724" y="117.459"/> + <use xlink:href="#glyph1-6" x="241.569797" y="117.459"/> + <use xlink:href="#glyph1-7" x="244.873727" y="117.459"/> + <use xlink:href="#glyph1-7" x="252.079823" y="117.459"/> + <use xlink:href="#glyph1-9" x="259.285919" y="117.459"/> + <use xlink:href="#glyph1-15" x="265.529386" y="117.459"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-21" x="277.412343" y="117.459"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-24" x="291.078533" y="117.459"/> + <use xlink:href="#glyph1-25" x="300.360525" y="117.459"/> + <use xlink:href="#glyph1-26" x="309.68412" y="117.459"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-27" x="68.742" y="89.962"/> + <use xlink:href="#glyph1-18" x="76.546333" y="89.962"/> + <use xlink:href="#glyph1-16" x="83.270397" y="89.962"/> + <use xlink:href="#glyph1-9" x="87.56278" y="89.962"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-12" x="37.407" y="103.909"/> + <use xlink:href="#glyph1-14" x="42.791129" y="103.909"/> + <use xlink:href="#glyph1-5" x="47.863945" y="103.909"/> + <use xlink:href="#glyph1-18" x="52.638361" y="103.909"/> + <use xlink:href="#glyph1-6" x="59.362424" y="103.909"/> + <use xlink:href="#glyph1-8" x="62.666354" y="103.909"/> + <use xlink:href="#glyph1-28" x="69.690254" y="103.909"/> + <use xlink:href="#glyph1-14" x="76.89635" y="103.909"/> + <use xlink:href="#glyph1-16" x="81.969166" y="103.909"/> + <use xlink:href="#glyph1-11" x="86.261549" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-5" x="92.898102" y="103.909"/> + <use xlink:href="#glyph1-29" x="97.672517" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-18" x="106.832566" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-5" x="113.154936" y="103.909"/> + <use xlink:href="#glyph1-7" x="117.929351" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-20" x="51.871" y="117.857"/> + <use xlink:href="#glyph1-17" x="60.911975" y="117.857"/> + <use xlink:href="#glyph1-12" x="68.118072" y="117.857"/> + <use xlink:href="#glyph1-14" x="73.5022" y="117.857"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-24" x="83.251878" y="117.857"/> + <use xlink:href="#glyph1-30" x="92.533869" y="117.857"/> + <use xlink:href="#glyph1-26" x="101.467248" y="117.857"/> + <use xlink:href="#glyph1-12" x="105.286206" y="117.857"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-27" x="418.874" y="103.909"/> + <use xlink:href="#glyph1-14" x="426.678333" y="103.909"/> + <use xlink:href="#glyph1-5" x="431.751149" y="103.909"/> + <use xlink:href="#glyph1-18" x="436.525564" y="103.909"/> + <use xlink:href="#glyph1-6" x="443.249628" y="103.909"/> + <use xlink:href="#glyph1-8" x="446.553558" y="103.909"/> + <use xlink:href="#glyph1-28" x="453.577458" y="103.909"/> + <use xlink:href="#glyph1-14" x="460.783554" y="103.909"/> + <use xlink:href="#glyph1-16" x="465.85637" y="103.909"/> + <use xlink:href="#glyph1-11" x="470.148753" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-5" x="476.785306" y="103.909"/> + <use xlink:href="#glyph1-29" x="481.559721" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-18" x="490.705423" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-5" x="497.04214" y="103.909"/> + <use xlink:href="#glyph1-7" x="501.816555" y="103.909"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-21" x="436.031" y="117.857"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph0-4" x="445.005" y="117.857"/> + <use xlink:href="#glyph0-4" x="452.387555" y="117.857"/> +</g> +<g style="fill:rgb(0%,0%,0%);fill-opacity:1;"> + <use xlink:href="#glyph1-24" x="464.452" y="117.857"/> + <use xlink:href="#glyph1-30" x="473.733991" y="117.857"/> + <use xlink:href="#glyph1-26" x="482.66737" y="117.857"/> + <use xlink:href="#glyph1-12" x="486.486329" y="117.857"/> +</g> +</g> +</svg> diff --git a/vendor/cxx/book/src/reference.md b/vendor/cxx/book/src/reference.md new file mode 100644 index 000000000..62ca35c51 --- /dev/null +++ b/vendor/cxx/book/src/reference.md @@ -0,0 +1,29 @@ +{{#title The bridge module — Rust ♡ C++}} +# The bridge module reference + +The ***[Core concepts](concepts.md)*** in chapter 2 covered the high level model +that CXX uses to represent a language boundary. This chapter builds on that one +to document an exhaustive reference on the syntax and functionality of +\#\[cxx::bridge\]. + +- ***[extern "Rust"](extern-rust.md)*** — exposing opaque Rust types, Rust + functions, Rust methods to C++; functions with lifetimes. + +- ***[extern "C++"](extern-c++.md)*** — binding opaque C++ types, C++ + functions, C++ member functions; sharing an opaque type definition across + multiple bridge modules or different crates; using bindgen-generated data + structures across a CXX bridge; Rust orphan-rule-compatible way to request + that particular glue code be emitted in a specific bridge module. + +- ***[Shared types](shared.md)*** — shared structs; shared enums; using + Rust as source of truth vs C++ as source of truth. + +- ***[Attributes](attributes.md)*** — working with namespaces; giving + functions a different name in their non-native language. + +- ***[Async functions](async.md)*** — integrating async C++ with async + Rust. + +- ***[Error handling](binding/result.md)*** — representing fallibility on + the language boundary; accessing a Rust error message from C++; customizing + the set of caught exceptions and their conversion to a Rust error message. diff --git a/vendor/cxx/book/src/shared.md b/vendor/cxx/book/src/shared.md new file mode 100644 index 000000000..4043db124 --- /dev/null +++ b/vendor/cxx/book/src/shared.md @@ -0,0 +1,246 @@ +{{#title Shared types — Rust ♡ C++}} +# Shared types + +Shared types enable *both* languages to have visibility into the internals of a +type. This is in contrast to opaque Rust types and opaque C++ types, for which +only one side gets to manipulate the internals. + +Unlike opaque types, the FFI bridge is allowed to pass and return shared types +by value. + +The order in which shared types are written is not important. C++ is order +sensitive but CXX will topologically sort and forward-declare your types as +necessary. + +## Shared structs and enums + +For enums, only C-like a.k.a. unit variants are currently supported. + +```rust,noplayground +#[cxx::bridge] +mod ffi { + struct PlayingCard { + suit: Suit, + value: u8, // A=1, J=11, Q=12, K=13 + } + + enum Suit { + Clubs, + Diamonds, + Hearts, + Spades, + } + + unsafe extern "C++" { + fn deck() -> Vec<PlayingCard>; + fn sort(cards: &mut Vec<PlayingCard>); + } +} +``` + +## The generated data structures + +Shared structs compile to an aggregate-initialization compatible C++ struct. + +Shared enums compile to a C++ `enum class` with a sufficiently sized integral +base type decided by CXX. + +```cpp +// generated header + +struct PlayingCard final { + Suit suit; + uint8_t value; +}; + +enum class Suit : uint8_t { + Clubs = 0, + Diamonds = 1, + Hearts = 2, + Spades = 3, +}; +``` + +Because it is not UB in C++ for an `enum class` to hold a value different from +all of the listed variants, we use a Rust representation for shared enums that +is compatible with this. The API you'll get is something like: + +```rust,noplayground +#[derive(Copy, Clone, PartialEq, Eq)] +#[repr(transparent)] +pub struct Suit { + pub repr: u8, +} +#[allow(non_upper_case_globals)] +impl Suit { + pub const Clubs: Self = Suit { repr: 0 }; + pub const Diamonds: Self = Suit { repr: 1 }; + pub const Hearts: Self = Suit { repr: 2 }; + pub const Spades: Self = Suit { repr: 3 }; +} +``` + +Notice you're free to treat the enum as an integer in Rust code via the public +`repr` field. + +Pattern matching with `match` still works but will require you to write wildcard +arms to handle the situation of an enum value that is not one of the listed +variants. + +```rust,noplayground +fn main() { + let suit: Suit = /*...*/; + match suit { + Suit::Clubs => ..., + Suit::Diamonds => ..., + Suit::Hearts => ..., + Suit::Spades => ..., + _ => ..., // fallback arm + } +} +``` + +If a shared struct has generic lifetime parameters, the lifetimes are simply not +represented on the C++ side. C++ code will need care when working with borrowed +data (as usual in C++). + +```rust,noplayground +#[cxx::bridge] +mod ffi { + struct Borrowed<'a> { + flags: &'a [&'a str], + } +} +``` + +```cpp +// generated header + +struct Borrowed final { + rust::Slice<const rust::Str> flags; +}; +``` + +## Enum discriminants + +You may provide explicit discriminants for some or all of the enum variants, in +which case those numbers will be propagated into the generated C++ `enum class`. + +```rust,noplayground +#[cxx::bridge] +mod ffi { + enum SmallPrime { + Two = 2, + Three = 3, + Five = 5, + Seven = 7, + } +} +``` + +Variants without an explicit discriminant are assigned the previous discriminant +plus 1. If the first variant has not been given an explicit discriminant, it is +assigned discriminant 0. + +By default CXX represents your enum using the smallest integer type capable of +fitting all the discriminants (whether explicit or implicit). If you need a +different representation for reasons, provide a `repr` attribute. + +```rust,noplayground +#[cxx::bridge] +mod ffi { + #[repr(i32)] + enum Enum { + Zero, + One, + Five = 5, + Six, + } +} +``` + +```cpp +// generated header + +enum class Enum : int32_t { + Zero = 0, + One = 1, + Five = 5, + Six = 6, +}; +``` + +## Extern enums + +If you need to interoperate with an already existing enum for which an existing +C++ definition is the source of truth, make sure that definition is provided by +some header in the bridge and then declare your enum *additionally* as an extern +C++ type. + +```rust,noplayground +#[cxx::bridge] +mod ffi { + enum Enum { + Yes, + No, + } + + extern "C++" { + include!("path/to/the/header.h"); + type Enum; + } +} +``` + +CXX will recognize this pattern and, instead of generating a C++ definition of +the enum, will instead generate C++ static assertions asserting that the +variants and discriminant values and integer representation written in Rust all +correctly match the existing C++ enum definition. + +Extern enums support all the same features as ordinary shared enums (explicit +discriminants, repr). Again, CXX will static assert that all of those things you +wrote are correct. + +## Derives + +The following standard traits are supported in `derive(...)` within the CXX +bridge module. + +- `Clone` +- `Copy` +- `Debug` +- `Default` +- `Eq` +- `Hash` +- `Ord` +- `PartialEq` +- `PartialOrd` + +Note that shared enums automatically always come with impls of `Copy`, `Clone`, +`Eq`, and `PartialEq`, so you're free to omit those derives on an enum. + +```rust,noplayground +#[cxx::bridge] +mod ffi { + #[derive(Clone, Debug, Hash)] + struct ExampleStruct { + x: u32, + s: String, + } + + #[derive(Hash, Ord, PartialOrd)] + enum ExampleEnum { + Yes, + No, + } +} +``` + +The derives naturally apply to *both* the Rust data type *and* the corresponding +C++ data type: + +- `Hash` gives you a specialization of [`template <> struct std::hash<T>`][hash] in C++ +- `PartialEq` produces `operator==` and `operator!=` +- `PartialOrd` produces `operator<`, `operator<=`, `operator>`, `operator>=` + +[hash]: https://en.cppreference.com/w/cpp/utility/hash diff --git a/vendor/cxx/book/src/tutorial.md b/vendor/cxx/book/src/tutorial.md new file mode 100644 index 000000000..2467282fb --- /dev/null +++ b/vendor/cxx/book/src/tutorial.md @@ -0,0 +1,688 @@ +{{#title Tutorial — Rust ♡ C++}} +# Tutorial: CXX blobstore client + +This example walks through a Rust application that calls into a C++ client of a +blobstore service. In fact we'll see calls going in both directions: Rust to C++ +as well as C++ to Rust. For your own use case it may be that you need just one +of these directions. + +All of the code involved in the example is shown on this page, but it's also +provided in runnable form in the *demo* directory of +<https://github.com/dtolnay/cxx>. To try it out directly, run `cargo run` from +that directory. + +This tutorial assumes you've read briefly about **shared structs**, **opaque +types**, and **functions** in the [*Core concepts*](concepts.md) page. + +## Creating the project + +We'll use Cargo, which is the build system commonly used by open source Rust +projects. (CXX works with other build systems too; refer to chapter 5.) + +Create a blank Cargo project: `mkdir cxx-demo`; `cd cxx-demo`; `cargo init`. + +Edit the Cargo.toml to add a dependency on the `cxx` crate: + +```toml,hidelines +## Cargo.toml +# [package] +# name = "cxx-demo" +# version = "0.1.0" +# edition = "2018" + +[dependencies] +cxx = "1.0" +``` + +We'll revisit this Cargo.toml later when we get to compiling some C++ code. + +## Defining the language boundary + +CXX relies on a description of the function signatures that will be exposed from +each language to the other. You provide this description using `extern` blocks +in a Rust module annotated with the `#[cxx::bridge]` attribute macro. + +We'll open with just the following at the top of src/main.rs and walk through +each item in detail. + +```rust,noplayground +// src/main.rs + +#[cxx::bridge] +mod ffi { + +} +# +# fn main() {} +``` + +The contents of this module will be everything that needs to be agreed upon by +both sides of the FFI boundary. + +## Calling a C++ function from Rust + +Let's obtain an instance of the C++ blobstore client, a class `BlobstoreClient` +defined in C++. + +We'll treat `BlobstoreClient` as an *opaque type* in CXX's classification so +that Rust does not need to assume anything about its implementation, not even +its size or alignment. In general, a C++ type might have a move-constructor +which is incompatible with Rust's move semantics, or may hold internal +references which cannot be modeled by Rust's borrowing system. Though there are +alternatives, the easiest way to not care about any such thing on an FFI +boundary is to require no knowledge about a type by treating it as opaque. + +Opaque types may only be manipulated behind an indirection such as a reference +`&`, a Rust `Box`, or a `UniquePtr` (Rust binding of `std::unique_ptr`). We'll +add a function through which C++ can return a `std::unique_ptr<BlobstoreClient>` +to Rust. + +```rust,noplayground +// src/main.rs + +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + include!("cxx-demo/include/blobstore.h"); + + type BlobstoreClient; + + fn new_blobstore_client() -> UniquePtr<BlobstoreClient>; + } +} + +fn main() { + let client = ffi::new_blobstore_client(); +} +``` + +The nature of `unsafe` extern blocks is clarified in more detail in the +[*extern "C++"*](extern-c++.md) chapter. In brief: the programmer is **not** +promising that the signatures they have typed in are accurate; that would be +unreasonable. CXX performs static assertions that the signatures exactly match +what is declared in C++. Rather, the programmer is only on the hook for things +that C++'s semantics are not precise enough to capture, i.e. things that would +only be represented at most by comments in the C++ code. In this case, it's +whether `new_blobstore_client` is safe or unsafe to call. If that function said +something like "must be called at most once or we'll stomp yer memery", Rust +would instead want to expose it as `unsafe fn new_blobstore_client`, this time +inside a safe `extern "C++"` block because the programmer is no longer on the +hook for any safety claim about the signature. + +If you build this file right now with `cargo build`, it won't build because we +haven't written a C++ implementation of `new_blobstore_client` nor instructed +Cargo about how to link it into the resulting binary. You'll see an error from +the linker like this: + +```console +error: linking with `cc` failed: exit code: 1 + | + = /bin/ld: target/debug/deps/cxx-demo-7cb7fddf3d67d880.rcgu.o: in function `cxx_demo::ffi::new_blobstore_client': + src/main.rs:1: undefined reference to `cxxbridge1$new_blobstore_client' + collect2: error: ld returned 1 exit status +``` + +## Adding in the C++ code + +In CXX's integration with Cargo, all #include paths begin with a crate name by +default (when not explicitly selected otherwise by a crate; see +`CFG.include_prefix` in chapter 5). That's why we see +`include!("cxx-demo/include/blobstore.h")` above — we'll be putting the +C++ header at relative path `include/blobstore.h` within the Rust crate. If your +crate is named something other than `cxx-demo` according to the `name` field in +Cargo.toml, you will need to use that name everywhere in place of `cxx-demo` +throughout this tutorial. + +```cpp +// include/blobstore.h + +#pragma once +#include <memory> + +class BlobstoreClient { +public: + BlobstoreClient(); +}; + +std::unique_ptr<BlobstoreClient> new_blobstore_client(); +``` + +```cpp +// src/blobstore.cc + +#include "cxx-demo/include/blobstore.h" + +BlobstoreClient::BlobstoreClient() {} + +std::unique_ptr<BlobstoreClient> new_blobstore_client() { + return std::unique_ptr<BlobstoreClient>(new BlobstoreClient()); +} +``` + +Using `std::make_unique` would work too, as long as you pass `-std=c++14` to the +C++ compiler as described later on. + +The placement in *include/* and *src/* is not significant; you can place C++ +code anywhere else in the crate as long as you use the right paths throughout +the tutorial. + +Be aware that *CXX does not look at any of these files.* You're free to put +arbitrary C++ code in here, #include your own libraries, etc. All we do is emit +static assertions against what you provide in the headers. + +## Compiling the C++ code with Cargo + +Cargo has a [build scripts] feature suitable for compiling non-Rust code. + +We need to introduce a new build-time dependency on CXX's C++ code generator in +Cargo.toml: + +```toml,hidelines +## Cargo.toml +# [package] +# name = "cxx-demo" +# version = "0.1.0" +# edition = "2018" + +[dependencies] +cxx = "1.0" + +[build-dependencies] +cxx-build = "1.0" +``` + +Then add a build.rs build script adjacent to Cargo.toml to run the cxx-build +code generator and C++ compiler. The relevant arguments are the path to the Rust +source file containing the cxx::bridge language boundary definition, and the +paths to any additional C++ source files to be compiled during the Rust crate's +build. + +```rust,noplayground +// build.rs + +fn main() { + cxx_build::bridge("src/main.rs") + .file("src/blobstore.cc") + .compile("cxx-demo"); +} +``` + +This build.rs would also be where you set up C++ compiler flags, for example if +you'd like to have access to `std::make_unique` from C++14. See the page on +***[Cargo-based builds](build/cargo.md)*** for more details about CXX's Cargo +integration. + +```rust,noplayground +# // build.rs +# +# fn main() { + cxx_build::bridge("src/main.rs") + .file("src/blobstore.cc") + .flag_if_supported("-std=c++14") + .compile("cxx-demo"); +# } +``` + +[build scripts]: https://doc.rust-lang.org/cargo/reference/build-scripts.html + +The project should now build and run successfully, though not do anything useful +yet. + +```console +cxx-demo$ cargo run + Compiling cxx-demo v0.1.0 + Finished dev [unoptimized + debuginfo] target(s) in 0.34s + Running `target/debug/cxx-demo` + +cxx-demo$ +``` + +## Calling a Rust function from C++ + +Our C++ blobstore supports a `put` operation for a discontiguous buffer upload. +For example we might be uploading snapshots of a circular buffer which would +tend to consist of 2 pieces, or fragments of a file spread across memory for +some other reason (like a rope data structure). + +We'll express this by handing off an iterator over contiguous borrowed chunks. +This loosely resembles the API of the widely used `bytes` crate's `Buf` trait. +During a `put`, we'll make C++ call back into Rust to obtain contiguous chunks +of the upload (all with no copying or allocation on the language boundary). In +reality the C++ client might contain some sophisticated batching of chunks +and/or parallel uploading that all of this ties into. + +```rust,noplayground +// src/main.rs + +#[cxx::bridge] +mod ffi { + extern "Rust" { + type MultiBuf; + + fn next_chunk(buf: &mut MultiBuf) -> &[u8]; + } + + unsafe extern "C++" { + include!("cxx-demo/include/blobstore.h"); + + type BlobstoreClient; + + fn new_blobstore_client() -> UniquePtr<BlobstoreClient>; + fn put(&self, parts: &mut MultiBuf) -> u64; + } +} +# +# fn main() { +# let client = ffi::new_blobstore_client(); +# } +``` + +Any signature having a `self` parameter (the Rust name for C++'s `this`) is +considered a method / non-static member function. If there is only one `type` in +the surrounding extern block, it'll be a method of that type. If there is more +than one `type`, you can disambiguate which one a method belongs to by writing +`self: &BlobstoreClient` in the argument list. + +As usual, now we need to provide Rust definitions of everything declared by the +`extern "Rust"` block and a C++ definition of the new signature declared by the +`extern "C++"` block. + +```rust,noplayground +// src/main.rs +# +# #[cxx::bridge] +# mod ffi { +# extern "Rust" { +# type MultiBuf; +# +# fn next_chunk(buf: &mut MultiBuf) -> &[u8]; +# } +# +# unsafe extern "C++" { +# include!("cxx-demo/include/blobstore.h"); +# +# type BlobstoreClient; +# +# fn new_blobstore_client() -> UniquePtr<BlobstoreClient>; +# fn put(&self, parts: &mut MultiBuf) -> u64; +# } +# } + +// An iterator over contiguous chunks of a discontiguous file object. Toy +// implementation uses a Vec<Vec<u8>> but in reality this might be iterating +// over some more complex Rust data structure like a rope, or maybe loading +// chunks lazily from somewhere. +pub struct MultiBuf { + chunks: Vec<Vec<u8>>, + pos: usize, +} + +pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] { + let next = buf.chunks.get(buf.pos); + buf.pos += 1; + next.map_or(&[], Vec::as_slice) +} +# +# fn main() { +# let client = ffi::new_blobstore_client(); +# } +``` + +```cpp,hidelines +// include/blobstore.h + +# #pragma once +# #include <memory> +# +struct MultiBuf; + +class BlobstoreClient { +public: + BlobstoreClient(); + uint64_t put(MultiBuf &buf) const; +}; +# +#std::unique_ptr<BlobstoreClient> new_blobstore_client(); +``` + +In blobstore.cc we're able to call the Rust `next_chunk` function, exposed to +C++ by a header `main.rs.h` generated by the CXX code generator. In CXX's Cargo +integration this generated header has a path containing the crate name, the +relative path of the Rust source file within the crate, and a `.rs.h` extension. + +```cpp,hidelines +// src/blobstore.cc + +##include "cxx-demo/include/blobstore.h" +##include "cxx-demo/src/main.rs.h" +##include <functional> +##include <string> +# +# BlobstoreClient::BlobstoreClient() {} +# +# std::unique_ptr<BlobstoreClient> new_blobstore_client() { +# return std::make_unique<BlobstoreClient>(); +# } + +// Upload a new blob and return a blobid that serves as a handle to the blob. +uint64_t BlobstoreClient::put(MultiBuf &buf) const { + // Traverse the caller's chunk iterator. + std::string contents; + while (true) { + auto chunk = next_chunk(buf); + if (chunk.size() == 0) { + break; + } + contents.append(reinterpret_cast<const char *>(chunk.data()), chunk.size()); + } + + // Pretend we did something useful to persist the data. + auto blobid = std::hash<std::string>{}(contents); + return blobid; +} +``` + +This is now ready to use. :) + +```rust,noplayground +// src/main.rs +# +# #[cxx::bridge] +# mod ffi { +# extern "Rust" { +# type MultiBuf; +# +# fn next_chunk(buf: &mut MultiBuf) -> &[u8]; +# } +# +# unsafe extern "C++" { +# include!("cxx-demo/include/blobstore.h"); +# +# type BlobstoreClient; +# +# fn new_blobstore_client() -> UniquePtr<BlobstoreClient>; +# fn put(&self, parts: &mut MultiBuf) -> u64; +# } +# } +# +# pub struct MultiBuf { +# chunks: Vec<Vec<u8>>, +# pos: usize, +# } +# pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] { +# let next = buf.chunks.get(buf.pos); +# buf.pos += 1; +# next.map_or(&[], Vec::as_slice) +# } + +fn main() { + let client = ffi::new_blobstore_client(); + + // Upload a blob. + let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()]; + let mut buf = MultiBuf { chunks, pos: 0 }; + let blobid = client.put(&mut buf); + println!("blobid = {}", blobid); +} +``` + +```console +cxx-demo$ cargo run + Compiling cxx-demo v0.1.0 + Finished dev [unoptimized + debuginfo] target(s) in 0.41s + Running `target/debug/cxx-demo` + +blobid = 9851996977040795552 +``` + +## Interlude: What gets generated? + +For the curious, it's easy to look behind the scenes at what CXX has done to +make these function calls work. You shouldn't need to do this during normal +usage of CXX, but for the purpose of this tutorial it can be educative. + +CXX comprises *two* code generators: a Rust one (which is the cxx::bridge +attribute procedural macro) and a C++ one. + +### Rust generated code + +It's easiest to view the output of the procedural macro by installing +[cargo-expand]. Then run `cargo expand ::ffi` to macro-expand the `mod ffi` +module. + +[cargo-expand]: https://github.com/dtolnay/cargo-expand + +```console +cxx-demo$ cargo install cargo-expand +cxx-demo$ cargo expand ::ffi +``` + +You'll see some deeply unpleasant code involving `#[repr(C)]`, `#[link_name]`, +and `#[export_name]`. + +### C++ generated code + +For debugging convenience, `cxx_build` links all generated C++ code into Cargo's +target directory under *target/cxxbridge/*. + +```console +cxx-demo$ exa -T target/cxxbridge/ +target/cxxbridge +├── cxx-demo +│ └── src +│ ├── main.rs.cc -> ../../../debug/build/cxx-demo-11c6f678ce5c3437/out/cxxbridge/sources/cxx-demo/src/main.rs.cc +│ └── main.rs.h -> ../../../debug/build/cxx-demo-11c6f678ce5c3437/out/cxxbridge/include/cxx-demo/src/main.rs.h +└── rust + └── cxx.h -> ~/.cargo/registry/src/github.com-1ecc6299db9ec823/cxx-1.0.0/include/cxx.h +``` + +In those files you'll see declarations or templates of any CXX Rust types +present in your language boundary (like `rust::Slice<T>` for `&[T]`) and `extern +"C"` signatures corresponding to your extern functions. + +If it fits your workflow better, the CXX C++ code generator is also available as +a standalone executable which outputs generated code to stdout. + +```console +cxx-demo$ cargo install cxxbridge-cmd +cxx-demo$ cxxbridge src/main.rs +``` + +## Shared data structures + +So far the calls in both directions above only used **opaque types**, not +**shared structs**. + +Shared structs are data structures whose complete definition is visible to both +languages, making it possible to pass them by value across the language +boundary. Shared structs translate to a C++ aggregate-initialization compatible +struct exactly matching the layout of the Rust one. + +As the last step of this demo, we'll use a shared struct `BlobMetadata` to pass +metadata about blobs between our Rust application and C++ blobstore client. + +```rust,noplayground +// src/main.rs + +#[cxx::bridge] +mod ffi { + struct BlobMetadata { + size: usize, + tags: Vec<String>, + } + + extern "Rust" { + // ... +# type MultiBuf; +# +# fn next_chunk(buf: &mut MultiBuf) -> &[u8]; + } + + unsafe extern "C++" { + // ... +# include!("cxx-demo/include/blobstore.h"); +# +# type BlobstoreClient; +# +# fn new_blobstore_client() -> UniquePtr<BlobstoreClient>; +# fn put(&self, parts: &mut MultiBuf) -> u64; + fn tag(&self, blobid: u64, tag: &str); + fn metadata(&self, blobid: u64) -> BlobMetadata; + } +} +# +# pub struct MultiBuf { +# chunks: Vec<Vec<u8>>, +# pos: usize, +# } +# pub fn next_chunk(buf: &mut MultiBuf) -> &[u8] { +# let next = buf.chunks.get(buf.pos); +# buf.pos += 1; +# next.map_or(&[], Vec::as_slice) +# } + +fn main() { + let client = ffi::new_blobstore_client(); + + // Upload a blob. + let chunks = vec![b"fearless".to_vec(), b"concurrency".to_vec()]; + let mut buf = MultiBuf { chunks, pos: 0 }; + let blobid = client.put(&mut buf); + println!("blobid = {}", blobid); + + // Add a tag. + client.tag(blobid, "rust"); + + // Read back the tags. + let metadata = client.metadata(blobid); + println!("tags = {:?}", metadata.tags); +} +``` + +```cpp,hidelines +// include/blobstore.h + +##pragma once +##include "rust/cxx.h" +# #include <memory> + +struct MultiBuf; +struct BlobMetadata; + +class BlobstoreClient { +public: + BlobstoreClient(); + uint64_t put(MultiBuf &buf) const; + void tag(uint64_t blobid, rust::Str tag) const; + BlobMetadata metadata(uint64_t blobid) const; + +private: + class impl; + std::shared_ptr<impl> impl; +}; +# +# std::unique_ptr<BlobstoreClient> new_blobstore_client(); +``` + +```cpp,hidelines +// src/blobstore.cc + +##include "cxx-demo/include/blobstore.h" +##include "cxx-demo/src/main.rs.h" +##include <algorithm> +##include <functional> +##include <set> +##include <string> +##include <unordered_map> + +// Toy implementation of an in-memory blobstore. +// +// In reality the implementation of BlobstoreClient could be a large +// complex C++ library. +class BlobstoreClient::impl { + friend BlobstoreClient; + using Blob = struct { + std::string data; + std::set<std::string> tags; + }; + std::unordered_map<uint64_t, Blob> blobs; +}; + +BlobstoreClient::BlobstoreClient() : impl(new class BlobstoreClient::impl) {} +# +# // Upload a new blob and return a blobid that serves as a handle to the blob. +# uint64_t BlobstoreClient::put(MultiBuf &buf) const { +# // Traverse the caller's chunk iterator. +# std::string contents; +# while (true) { +# auto chunk = next_chunk(buf); +# if (chunk.size() == 0) { +# break; +# } +# contents.append(reinterpret_cast<const char *>(chunk.data()), chunk.size()); +# } +# +# // Insert into map and provide caller the handle. +# auto blobid = std::hash<std::string>{}(contents); +# impl->blobs[blobid] = {std::move(contents), {}}; +# return blobid; +# } + +// Add tag to an existing blob. +void BlobstoreClient::tag(uint64_t blobid, rust::Str tag) const { + impl->blobs[blobid].tags.emplace(tag); +} + +// Retrieve metadata about a blob. +BlobMetadata BlobstoreClient::metadata(uint64_t blobid) const { + BlobMetadata metadata{}; + auto blob = impl->blobs.find(blobid); + if (blob != impl->blobs.end()) { + metadata.size = blob->second.data.size(); + std::for_each(blob->second.tags.cbegin(), blob->second.tags.cend(), + [&](auto &t) { metadata.tags.emplace_back(t); }); + } + return metadata; +} +# +# std::unique_ptr<BlobstoreClient> new_blobstore_client() { +# return std::make_unique<BlobstoreClient>(); +# } +``` + +```console +cxx-demo$ cargo run + Running `target/debug/cxx-demo` + +blobid = 9851996977040795552 +tags = ["rust"] +``` + +*You've now seen all the code involved in the tutorial. It's available all +together in runnable form in the* demo *directory of +<https://github.com/dtolnay/cxx>. You can run it directly without stepping +through the steps above by running `cargo run` from that directory.* + +<br> + +# Takeaways + +The key contribution of CXX is it gives you Rust–C++ interop in which +*all* of the Rust side of the code you write *really* looks like you are just +writing normal Rust, and the C++ side *really* looks like you are just writing +normal C++. + +You've seen in this tutorial that none of the code involved feels like C or like +the usual perilous "FFI glue" prone to leaks or memory safety flaws. + +An expressive system of opaque types, shared types, and key standard library +type bindings enables API design on the language boundary that captures the +proper ownership and borrowing contracts of the interface. + +CXX plays to the strengths of the Rust type system *and* C++ type system *and* +the programmer's intuitions. An individual working on the C++ side without a +Rust background, or the Rust side without a C++ background, will be able to +apply all their usual intuitions and best practices about development in their +language to maintain a correct FFI. + +<br><br> diff --git a/vendor/cxx/book/theme/head.hbs b/vendor/cxx/book/theme/head.hbs new file mode 100644 index 000000000..4210276b0 --- /dev/null +++ b/vendor/cxx/book/theme/head.hbs @@ -0,0 +1,7 @@ + <script async src="https://www.googletagmanager.com/gtag/js?id=G-DG41MK6DDN"></script> + <script> + window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', 'G-DG41MK6DDN', {'anonymize_ip': true}); + </script> diff --git a/vendor/cxx/build.rs b/vendor/cxx/build.rs new file mode 100644 index 000000000..9158b1c84 --- /dev/null +++ b/vendor/cxx/build.rs @@ -0,0 +1,49 @@ +use std::env; +use std::path::Path; +use std::process::Command; + +fn main() { + cc::Build::new() + .file("src/cxx.cc") + .cpp(true) + .cpp_link_stdlib(None) // linked via link-cplusplus crate + .flag_if_supported(cxxbridge_flags::STD) + .warnings_into_errors(cfg!(deny_warnings)) + .compile("cxxbridge1"); + + println!("cargo:rerun-if-changed=src/cxx.cc"); + println!("cargo:rerun-if-changed=include/cxx.h"); + println!("cargo:rustc-cfg=built_with_cargo"); + + if let Some(manifest_dir) = env::var_os("CARGO_MANIFEST_DIR") { + let cxx_h = Path::new(&manifest_dir).join("include").join("cxx.h"); + println!("cargo:HEADER={}", cxx_h.to_string_lossy()); + } + + if let Some(rustc) = rustc_version() { + if rustc.minor < 60 { + println!("cargo:warning=The cxx crate requires a rustc version 1.60.0 or newer."); + println!( + "cargo:warning=You appear to be building with: {}", + rustc.version, + ); + } + } +} + +struct RustVersion { + version: String, + minor: u32, +} + +fn rustc_version() -> Option<RustVersion> { + let rustc = env::var_os("RUSTC")?; + let output = Command::new(rustc).arg("--version").output().ok()?; + let version = String::from_utf8(output.stdout).ok()?; + let mut pieces = version.split('.'); + if pieces.next() != Some("rustc 1") { + return None; + } + let minor = pieces.next()?.parse().ok()?; + Some(RustVersion { version, minor }) +} diff --git a/vendor/cxx/compile_flags.txt b/vendor/cxx/compile_flags.txt new file mode 100644 index 000000000..c24e3b5e5 --- /dev/null +++ b/vendor/cxx/compile_flags.txt @@ -0,0 +1 @@ +-std=c++11 diff --git a/vendor/cxx/include/cxx.h b/vendor/cxx/include/cxx.h new file mode 100644 index 000000000..907ee829f --- /dev/null +++ b/vendor/cxx/include/cxx.h @@ -0,0 +1,1111 @@ +#pragma once +#include <algorithm> +#include <array> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <exception> +#include <initializer_list> +#include <iosfwd> +#include <iterator> +#include <new> +#include <stdexcept> +#include <string> +#include <type_traits> +#include <utility> +#include <vector> +#if defined(_WIN32) +#include <basetsd.h> +#else +#include <sys/types.h> +#endif + +namespace rust { +inline namespace cxxbridge1 { + +struct unsafe_bitcopy_t; + +namespace { +template <typename T> +class impl; +} + +#ifndef CXXBRIDGE1_RUST_STRING +#define CXXBRIDGE1_RUST_STRING +// https://cxx.rs/binding/string.html +class String final { +public: + String() noexcept; + String(const String &) noexcept; + String(String &&) noexcept; + ~String() noexcept; + + String(const std::string &); + String(const char *); + String(const char *, std::size_t); + String(const char16_t *); + String(const char16_t *, std::size_t); + + // Replace invalid Unicode data with the replacement character (U+FFFD). + static String lossy(const std::string &) noexcept; + static String lossy(const char *) noexcept; + static String lossy(const char *, std::size_t) noexcept; + static String lossy(const char16_t *) noexcept; + static String lossy(const char16_t *, std::size_t) noexcept; + + String &operator=(const String &) &noexcept; + String &operator=(String &&) &noexcept; + + explicit operator std::string() const; + + // Note: no null terminator. + const char *data() const noexcept; + std::size_t size() const noexcept; + std::size_t length() const noexcept; + bool empty() const noexcept; + + const char *c_str() noexcept; + + std::size_t capacity() const noexcept; + void reserve(size_t new_cap) noexcept; + + using iterator = char *; + iterator begin() noexcept; + iterator end() noexcept; + + using const_iterator = const char *; + const_iterator begin() const noexcept; + const_iterator end() const noexcept; + const_iterator cbegin() const noexcept; + const_iterator cend() const noexcept; + + bool operator==(const String &) const noexcept; + bool operator!=(const String &) const noexcept; + bool operator<(const String &) const noexcept; + bool operator<=(const String &) const noexcept; + bool operator>(const String &) const noexcept; + bool operator>=(const String &) const noexcept; + + void swap(String &) noexcept; + + // Internal API only intended for the cxxbridge code generator. + String(unsafe_bitcopy_t, const String &) noexcept; + +private: + struct lossy_t; + String(lossy_t, const char *, std::size_t) noexcept; + String(lossy_t, const char16_t *, std::size_t) noexcept; + friend void swap(String &lhs, String &rhs) noexcept { lhs.swap(rhs); } + + // Size and alignment statically verified by rust_string.rs. + std::array<std::uintptr_t, 3> repr; +}; +#endif // CXXBRIDGE1_RUST_STRING + +#ifndef CXXBRIDGE1_RUST_STR +#define CXXBRIDGE1_RUST_STR +// https://cxx.rs/binding/str.html +class Str final { +public: + Str() noexcept; + Str(const String &) noexcept; + Str(const std::string &); + Str(const char *); + Str(const char *, std::size_t); + + Str &operator=(const Str &) &noexcept = default; + + explicit operator std::string() const; + + // Note: no null terminator. + const char *data() const noexcept; + std::size_t size() const noexcept; + std::size_t length() const noexcept; + bool empty() const noexcept; + + // Important in order for System V ABI to pass in registers. + Str(const Str &) noexcept = default; + ~Str() noexcept = default; + + using iterator = const char *; + using const_iterator = const char *; + const_iterator begin() const noexcept; + const_iterator end() const noexcept; + const_iterator cbegin() const noexcept; + const_iterator cend() const noexcept; + + bool operator==(const Str &) const noexcept; + bool operator!=(const Str &) const noexcept; + bool operator<(const Str &) const noexcept; + bool operator<=(const Str &) const noexcept; + bool operator>(const Str &) const noexcept; + bool operator>=(const Str &) const noexcept; + + void swap(Str &) noexcept; + +private: + class uninit; + Str(uninit) noexcept; + friend impl<Str>; + + std::array<std::uintptr_t, 2> repr; +}; +#endif // CXXBRIDGE1_RUST_STR + +#ifndef CXXBRIDGE1_RUST_SLICE +namespace detail { +template <bool> +struct copy_assignable_if {}; + +template <> +struct copy_assignable_if<false> { + copy_assignable_if() noexcept = default; + copy_assignable_if(const copy_assignable_if &) noexcept = default; + copy_assignable_if &operator=(const copy_assignable_if &) &noexcept = delete; + copy_assignable_if &operator=(copy_assignable_if &&) &noexcept = default; +}; +} // namespace detail + +// https://cxx.rs/binding/slice.html +template <typename T> +class Slice final + : private detail::copy_assignable_if<std::is_const<T>::value> { +public: + using value_type = T; + + Slice() noexcept; + Slice(T *, std::size_t count) noexcept; + + Slice &operator=(const Slice<T> &) &noexcept = default; + Slice &operator=(Slice<T> &&) &noexcept = default; + + T *data() const noexcept; + std::size_t size() const noexcept; + std::size_t length() const noexcept; + bool empty() const noexcept; + + T &operator[](std::size_t n) const noexcept; + T &at(std::size_t n) const; + T &front() const noexcept; + T &back() const noexcept; + + // Important in order for System V ABI to pass in registers. + Slice(const Slice<T> &) noexcept = default; + ~Slice() noexcept = default; + + class iterator; + iterator begin() const noexcept; + iterator end() const noexcept; + + void swap(Slice &) noexcept; + +private: + class uninit; + Slice(uninit) noexcept; + friend impl<Slice>; + friend void sliceInit(void *, const void *, std::size_t) noexcept; + friend void *slicePtr(const void *) noexcept; + friend std::size_t sliceLen(const void *) noexcept; + + std::array<std::uintptr_t, 2> repr; +}; + +template <typename T> +class Slice<T>::iterator final { +public: + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = typename std::add_pointer<T>::type; + using reference = typename std::add_lvalue_reference<T>::type; + + reference operator*() const noexcept; + pointer operator->() const noexcept; + reference operator[](difference_type) const noexcept; + + iterator &operator++() noexcept; + iterator operator++(int) noexcept; + iterator &operator--() noexcept; + iterator operator--(int) noexcept; + + iterator &operator+=(difference_type) noexcept; + iterator &operator-=(difference_type) noexcept; + iterator operator+(difference_type) const noexcept; + iterator operator-(difference_type) const noexcept; + difference_type operator-(const iterator &) const noexcept; + + bool operator==(const iterator &) const noexcept; + bool operator!=(const iterator &) const noexcept; + bool operator<(const iterator &) const noexcept; + bool operator<=(const iterator &) const noexcept; + bool operator>(const iterator &) const noexcept; + bool operator>=(const iterator &) const noexcept; + +private: + friend class Slice; + void *pos; + std::size_t stride; +}; +#endif // CXXBRIDGE1_RUST_SLICE + +#ifndef CXXBRIDGE1_RUST_BOX +// https://cxx.rs/binding/box.html +template <typename T> +class Box final { +public: + using element_type = T; + using const_pointer = + typename std::add_pointer<typename std::add_const<T>::type>::type; + using pointer = typename std::add_pointer<T>::type; + + Box() = delete; + Box(Box &&) noexcept; + ~Box() noexcept; + + explicit Box(const T &); + explicit Box(T &&); + + Box &operator=(Box &&) &noexcept; + + const T *operator->() const noexcept; + const T &operator*() const noexcept; + T *operator->() noexcept; + T &operator*() noexcept; + + template <typename... Fields> + static Box in_place(Fields &&...); + + void swap(Box &) noexcept; + + // Important: requires that `raw` came from an into_raw call. Do not pass a + // pointer from `new` or any other source. + static Box from_raw(T *) noexcept; + + T *into_raw() noexcept; + + /* Deprecated */ using value_type = element_type; + +private: + class uninit; + class allocation; + Box(uninit) noexcept; + void drop() noexcept; + + friend void swap(Box &lhs, Box &rhs) noexcept { lhs.swap(rhs); } + + T *ptr; +}; +#endif // CXXBRIDGE1_RUST_BOX + +#ifndef CXXBRIDGE1_RUST_VEC +// https://cxx.rs/binding/vec.html +template <typename T> +class Vec final { +public: + using value_type = T; + + Vec() noexcept; + Vec(std::initializer_list<T>); + Vec(const Vec &); + Vec(Vec &&) noexcept; + ~Vec() noexcept; + + Vec &operator=(Vec &&) &noexcept; + Vec &operator=(const Vec &) &; + + std::size_t size() const noexcept; + bool empty() const noexcept; + const T *data() const noexcept; + T *data() noexcept; + std::size_t capacity() const noexcept; + + const T &operator[](std::size_t n) const noexcept; + const T &at(std::size_t n) const; + const T &front() const noexcept; + const T &back() const noexcept; + + T &operator[](std::size_t n) noexcept; + T &at(std::size_t n); + T &front() noexcept; + T &back() noexcept; + + void reserve(std::size_t new_cap); + void push_back(const T &value); + void push_back(T &&value); + template <typename... Args> + void emplace_back(Args &&...args); + void truncate(std::size_t len); + void clear(); + + using iterator = typename Slice<T>::iterator; + iterator begin() noexcept; + iterator end() noexcept; + + using const_iterator = typename Slice<const T>::iterator; + const_iterator begin() const noexcept; + const_iterator end() const noexcept; + const_iterator cbegin() const noexcept; + const_iterator cend() const noexcept; + + void swap(Vec &) noexcept; + + // Internal API only intended for the cxxbridge code generator. + Vec(unsafe_bitcopy_t, const Vec &) noexcept; + +private: + void reserve_total(std::size_t new_cap) noexcept; + void set_len(std::size_t len) noexcept; + void drop() noexcept; + + friend void swap(Vec &lhs, Vec &rhs) noexcept { lhs.swap(rhs); } + + // Size and alignment statically verified by rust_vec.rs. + std::array<std::uintptr_t, 3> repr; +}; +#endif // CXXBRIDGE1_RUST_VEC + +#ifndef CXXBRIDGE1_RUST_FN +// https://cxx.rs/binding/fn.html +template <typename Signature> +class Fn; + +template <typename Ret, typename... Args> +class Fn<Ret(Args...)> final { +public: + Ret operator()(Args... args) const noexcept; + Fn operator*() const noexcept; + +private: + Ret (*trampoline)(Args..., void *fn) noexcept; + void *fn; +}; +#endif // CXXBRIDGE1_RUST_FN + +#ifndef CXXBRIDGE1_RUST_ERROR +#define CXXBRIDGE1_RUST_ERROR +// https://cxx.rs/binding/result.html +class Error final : public std::exception { +public: + Error(const Error &); + Error(Error &&) noexcept; + ~Error() noexcept override; + + Error &operator=(const Error &) &; + Error &operator=(Error &&) &noexcept; + + const char *what() const noexcept override; + +private: + Error() noexcept = default; + friend impl<Error>; + const char *msg; + std::size_t len; +}; +#endif // CXXBRIDGE1_RUST_ERROR + +#ifndef CXXBRIDGE1_RUST_ISIZE +#define CXXBRIDGE1_RUST_ISIZE +#if defined(_WIN32) +using isize = SSIZE_T; +#else +using isize = ssize_t; +#endif +#endif // CXXBRIDGE1_RUST_ISIZE + +std::ostream &operator<<(std::ostream &, const String &); +std::ostream &operator<<(std::ostream &, const Str &); + +#ifndef CXXBRIDGE1_RUST_OPAQUE +#define CXXBRIDGE1_RUST_OPAQUE +// Base class of generated opaque Rust types. +class Opaque { +public: + Opaque() = delete; + Opaque(const Opaque &) = delete; + ~Opaque() = delete; +}; +#endif // CXXBRIDGE1_RUST_OPAQUE + +template <typename T> +std::size_t size_of(); +template <typename T> +std::size_t align_of(); + +// IsRelocatable<T> is used in assertions that a C++ type passed by value +// between Rust and C++ is soundly relocatable by Rust. +// +// There may be legitimate reasons to opt out of the check for support of types +// that the programmer knows are soundly Rust-movable despite not being +// recognized as such by the C++ type system due to a move constructor or +// destructor. To opt out of the relocatability check, do either of the +// following things in any header used by `include!` in the bridge. +// +// --- if you define the type: +// struct MyType { +// ... +// + using IsRelocatable = std::true_type; +// }; +// +// --- otherwise: +// + template <> +// + struct rust::IsRelocatable<MyType> : std::true_type {}; +template <typename T> +struct IsRelocatable; + +using u8 = std::uint8_t; +using u16 = std::uint16_t; +using u32 = std::uint32_t; +using u64 = std::uint64_t; +using usize = std::size_t; // see static asserts in cxx.cc +using i8 = std::int8_t; +using i16 = std::int16_t; +using i32 = std::int32_t; +using i64 = std::int64_t; +using f32 = float; +using f64 = double; + +// Snake case aliases for use in code that uses this style for type names. +using string = String; +using str = Str; +template <typename T> +using slice = Slice<T>; +template <typename T> +using box = Box<T>; +template <typename T> +using vec = Vec<T>; +using error = Error; +template <typename Signature> +using fn = Fn<Signature>; +template <typename T> +using is_relocatable = IsRelocatable<T>; + + + +//////////////////////////////////////////////////////////////////////////////// +/// end public API, begin implementation details + +#ifndef CXXBRIDGE1_PANIC +#define CXXBRIDGE1_PANIC +template <typename Exception> +void panic [[noreturn]] (const char *msg); +#endif // CXXBRIDGE1_PANIC + +#ifndef CXXBRIDGE1_RUST_FN +#define CXXBRIDGE1_RUST_FN +template <typename Ret, typename... Args> +Ret Fn<Ret(Args...)>::operator()(Args... args) const noexcept { + return (*this->trampoline)(std::forward<Args>(args)..., this->fn); +} + +template <typename Ret, typename... Args> +Fn<Ret(Args...)> Fn<Ret(Args...)>::operator*() const noexcept { + return *this; +} +#endif // CXXBRIDGE1_RUST_FN + +#ifndef CXXBRIDGE1_RUST_BITCOPY_T +#define CXXBRIDGE1_RUST_BITCOPY_T +struct unsafe_bitcopy_t final { + explicit unsafe_bitcopy_t() = default; +}; +#endif // CXXBRIDGE1_RUST_BITCOPY_T + +#ifndef CXXBRIDGE1_RUST_BITCOPY +#define CXXBRIDGE1_RUST_BITCOPY +constexpr unsafe_bitcopy_t unsafe_bitcopy{}; +#endif // CXXBRIDGE1_RUST_BITCOPY + +#ifndef CXXBRIDGE1_RUST_SLICE +#define CXXBRIDGE1_RUST_SLICE +template <typename T> +Slice<T>::Slice() noexcept { + sliceInit(this, reinterpret_cast<void *>(align_of<T>()), 0); +} + +template <typename T> +Slice<T>::Slice(T *s, std::size_t count) noexcept { + assert(s != nullptr || count == 0); + sliceInit(this, + s == nullptr && count == 0 + ? reinterpret_cast<void *>(align_of<T>()) + : const_cast<typename std::remove_const<T>::type *>(s), + count); +} + +template <typename T> +T *Slice<T>::data() const noexcept { + return reinterpret_cast<T *>(slicePtr(this)); +} + +template <typename T> +std::size_t Slice<T>::size() const noexcept { + return sliceLen(this); +} + +template <typename T> +std::size_t Slice<T>::length() const noexcept { + return this->size(); +} + +template <typename T> +bool Slice<T>::empty() const noexcept { + return this->size() == 0; +} + +template <typename T> +T &Slice<T>::operator[](std::size_t n) const noexcept { + assert(n < this->size()); + auto ptr = static_cast<char *>(slicePtr(this)) + size_of<T>() * n; + return *reinterpret_cast<T *>(ptr); +} + +template <typename T> +T &Slice<T>::at(std::size_t n) const { + if (n >= this->size()) { + panic<std::out_of_range>("rust::Slice index out of range"); + } + return (*this)[n]; +} + +template <typename T> +T &Slice<T>::front() const noexcept { + assert(!this->empty()); + return (*this)[0]; +} + +template <typename T> +T &Slice<T>::back() const noexcept { + assert(!this->empty()); + return (*this)[this->size() - 1]; +} + +template <typename T> +typename Slice<T>::iterator::reference +Slice<T>::iterator::operator*() const noexcept { + return *static_cast<T *>(this->pos); +} + +template <typename T> +typename Slice<T>::iterator::pointer +Slice<T>::iterator::operator->() const noexcept { + return static_cast<T *>(this->pos); +} + +template <typename T> +typename Slice<T>::iterator::reference Slice<T>::iterator::operator[]( + typename Slice<T>::iterator::difference_type n) const noexcept { + auto ptr = static_cast<char *>(this->pos) + this->stride * n; + return *reinterpret_cast<T *>(ptr); +} + +template <typename T> +typename Slice<T>::iterator &Slice<T>::iterator::operator++() noexcept { + this->pos = static_cast<char *>(this->pos) + this->stride; + return *this; +} + +template <typename T> +typename Slice<T>::iterator Slice<T>::iterator::operator++(int) noexcept { + auto ret = iterator(*this); + this->pos = static_cast<char *>(this->pos) + this->stride; + return ret; +} + +template <typename T> +typename Slice<T>::iterator &Slice<T>::iterator::operator--() noexcept { + this->pos = static_cast<char *>(this->pos) - this->stride; + return *this; +} + +template <typename T> +typename Slice<T>::iterator Slice<T>::iterator::operator--(int) noexcept { + auto ret = iterator(*this); + this->pos = static_cast<char *>(this->pos) - this->stride; + return ret; +} + +template <typename T> +typename Slice<T>::iterator &Slice<T>::iterator::operator+=( + typename Slice<T>::iterator::difference_type n) noexcept { + this->pos = static_cast<char *>(this->pos) + this->stride * n; + return *this; +} + +template <typename T> +typename Slice<T>::iterator &Slice<T>::iterator::operator-=( + typename Slice<T>::iterator::difference_type n) noexcept { + this->pos = static_cast<char *>(this->pos) - this->stride * n; + return *this; +} + +template <typename T> +typename Slice<T>::iterator Slice<T>::iterator::operator+( + typename Slice<T>::iterator::difference_type n) const noexcept { + auto ret = iterator(*this); + ret.pos = static_cast<char *>(this->pos) + this->stride * n; + return ret; +} + +template <typename T> +typename Slice<T>::iterator Slice<T>::iterator::operator-( + typename Slice<T>::iterator::difference_type n) const noexcept { + auto ret = iterator(*this); + ret.pos = static_cast<char *>(this->pos) - this->stride * n; + return ret; +} + +template <typename T> +typename Slice<T>::iterator::difference_type +Slice<T>::iterator::operator-(const iterator &other) const noexcept { + auto diff = std::distance(static_cast<char *>(other.pos), + static_cast<char *>(this->pos)); + return diff / this->stride; +} + +template <typename T> +bool Slice<T>::iterator::operator==(const iterator &other) const noexcept { + return this->pos == other.pos; +} + +template <typename T> +bool Slice<T>::iterator::operator!=(const iterator &other) const noexcept { + return this->pos != other.pos; +} + +template <typename T> +bool Slice<T>::iterator::operator<(const iterator &other) const noexcept { + return this->pos < other.pos; +} + +template <typename T> +bool Slice<T>::iterator::operator<=(const iterator &other) const noexcept { + return this->pos <= other.pos; +} + +template <typename T> +bool Slice<T>::iterator::operator>(const iterator &other) const noexcept { + return this->pos > other.pos; +} + +template <typename T> +bool Slice<T>::iterator::operator>=(const iterator &other) const noexcept { + return this->pos >= other.pos; +} + +template <typename T> +typename Slice<T>::iterator Slice<T>::begin() const noexcept { + iterator it; + it.pos = slicePtr(this); + it.stride = size_of<T>(); + return it; +} + +template <typename T> +typename Slice<T>::iterator Slice<T>::end() const noexcept { + iterator it = this->begin(); + it.pos = static_cast<char *>(it.pos) + it.stride * this->size(); + return it; +} + +template <typename T> +void Slice<T>::swap(Slice &rhs) noexcept { + std::swap(*this, rhs); +} +#endif // CXXBRIDGE1_RUST_SLICE + +#ifndef CXXBRIDGE1_RUST_BOX +#define CXXBRIDGE1_RUST_BOX +template <typename T> +class Box<T>::uninit {}; + +template <typename T> +class Box<T>::allocation { + static T *alloc() noexcept; + static void dealloc(T *) noexcept; + +public: + allocation() noexcept : ptr(alloc()) {} + ~allocation() noexcept { + if (this->ptr) { + dealloc(this->ptr); + } + } + T *ptr; +}; + +template <typename T> +Box<T>::Box(Box &&other) noexcept : ptr(other.ptr) { + other.ptr = nullptr; +} + +template <typename T> +Box<T>::Box(const T &val) { + allocation alloc; + ::new (alloc.ptr) T(val); + this->ptr = alloc.ptr; + alloc.ptr = nullptr; +} + +template <typename T> +Box<T>::Box(T &&val) { + allocation alloc; + ::new (alloc.ptr) T(std::move(val)); + this->ptr = alloc.ptr; + alloc.ptr = nullptr; +} + +template <typename T> +Box<T>::~Box() noexcept { + if (this->ptr) { + this->drop(); + } +} + +template <typename T> +Box<T> &Box<T>::operator=(Box &&other) &noexcept { + if (this->ptr) { + this->drop(); + } + this->ptr = other.ptr; + other.ptr = nullptr; + return *this; +} + +template <typename T> +const T *Box<T>::operator->() const noexcept { + return this->ptr; +} + +template <typename T> +const T &Box<T>::operator*() const noexcept { + return *this->ptr; +} + +template <typename T> +T *Box<T>::operator->() noexcept { + return this->ptr; +} + +template <typename T> +T &Box<T>::operator*() noexcept { + return *this->ptr; +} + +template <typename T> +template <typename... Fields> +Box<T> Box<T>::in_place(Fields &&...fields) { + allocation alloc; + auto ptr = alloc.ptr; + ::new (ptr) T{std::forward<Fields>(fields)...}; + alloc.ptr = nullptr; + return from_raw(ptr); +} + +template <typename T> +void Box<T>::swap(Box &rhs) noexcept { + using std::swap; + swap(this->ptr, rhs.ptr); +} + +template <typename T> +Box<T> Box<T>::from_raw(T *raw) noexcept { + Box box = uninit{}; + box.ptr = raw; + return box; +} + +template <typename T> +T *Box<T>::into_raw() noexcept { + T *raw = this->ptr; + this->ptr = nullptr; + return raw; +} + +template <typename T> +Box<T>::Box(uninit) noexcept {} +#endif // CXXBRIDGE1_RUST_BOX + +#ifndef CXXBRIDGE1_RUST_VEC +#define CXXBRIDGE1_RUST_VEC +template <typename T> +Vec<T>::Vec(std::initializer_list<T> init) : Vec{} { + this->reserve_total(init.size()); + std::move(init.begin(), init.end(), std::back_inserter(*this)); +} + +template <typename T> +Vec<T>::Vec(const Vec &other) : Vec() { + this->reserve_total(other.size()); + std::copy(other.begin(), other.end(), std::back_inserter(*this)); +} + +template <typename T> +Vec<T>::Vec(Vec &&other) noexcept : repr(other.repr) { + new (&other) Vec(); +} + +template <typename T> +Vec<T>::~Vec() noexcept { + this->drop(); +} + +template <typename T> +Vec<T> &Vec<T>::operator=(Vec &&other) &noexcept { + this->drop(); + this->repr = other.repr; + new (&other) Vec(); + return *this; +} + +template <typename T> +Vec<T> &Vec<T>::operator=(const Vec &other) & { + if (this != &other) { + this->drop(); + new (this) Vec(other); + } + return *this; +} + +template <typename T> +bool Vec<T>::empty() const noexcept { + return this->size() == 0; +} + +template <typename T> +T *Vec<T>::data() noexcept { + return const_cast<T *>(const_cast<const Vec<T> *>(this)->data()); +} + +template <typename T> +const T &Vec<T>::operator[](std::size_t n) const noexcept { + assert(n < this->size()); + auto data = reinterpret_cast<const char *>(this->data()); + return *reinterpret_cast<const T *>(data + n * size_of<T>()); +} + +template <typename T> +const T &Vec<T>::at(std::size_t n) const { + if (n >= this->size()) { + panic<std::out_of_range>("rust::Vec index out of range"); + } + return (*this)[n]; +} + +template <typename T> +const T &Vec<T>::front() const noexcept { + assert(!this->empty()); + return (*this)[0]; +} + +template <typename T> +const T &Vec<T>::back() const noexcept { + assert(!this->empty()); + return (*this)[this->size() - 1]; +} + +template <typename T> +T &Vec<T>::operator[](std::size_t n) noexcept { + assert(n < this->size()); + auto data = reinterpret_cast<char *>(this->data()); + return *reinterpret_cast<T *>(data + n * size_of<T>()); +} + +template <typename T> +T &Vec<T>::at(std::size_t n) { + if (n >= this->size()) { + panic<std::out_of_range>("rust::Vec index out of range"); + } + return (*this)[n]; +} + +template <typename T> +T &Vec<T>::front() noexcept { + assert(!this->empty()); + return (*this)[0]; +} + +template <typename T> +T &Vec<T>::back() noexcept { + assert(!this->empty()); + return (*this)[this->size() - 1]; +} + +template <typename T> +void Vec<T>::reserve(std::size_t new_cap) { + this->reserve_total(new_cap); +} + +template <typename T> +void Vec<T>::push_back(const T &value) { + this->emplace_back(value); +} + +template <typename T> +void Vec<T>::push_back(T &&value) { + this->emplace_back(std::move(value)); +} + +template <typename T> +template <typename... Args> +void Vec<T>::emplace_back(Args &&...args) { + auto size = this->size(); + this->reserve_total(size + 1); + ::new (reinterpret_cast<T *>(reinterpret_cast<char *>(this->data()) + + size * size_of<T>())) + T(std::forward<Args>(args)...); + this->set_len(size + 1); +} + +template <typename T> +void Vec<T>::clear() { + this->truncate(0); +} + +template <typename T> +typename Vec<T>::iterator Vec<T>::begin() noexcept { + return Slice<T>(this->data(), this->size()).begin(); +} + +template <typename T> +typename Vec<T>::iterator Vec<T>::end() noexcept { + return Slice<T>(this->data(), this->size()).end(); +} + +template <typename T> +typename Vec<T>::const_iterator Vec<T>::begin() const noexcept { + return this->cbegin(); +} + +template <typename T> +typename Vec<T>::const_iterator Vec<T>::end() const noexcept { + return this->cend(); +} + +template <typename T> +typename Vec<T>::const_iterator Vec<T>::cbegin() const noexcept { + return Slice<const T>(this->data(), this->size()).begin(); +} + +template <typename T> +typename Vec<T>::const_iterator Vec<T>::cend() const noexcept { + return Slice<const T>(this->data(), this->size()).end(); +} + +template <typename T> +void Vec<T>::swap(Vec &rhs) noexcept { + using std::swap; + swap(this->repr, rhs.repr); +} + +// Internal API only intended for the cxxbridge code generator. +template <typename T> +Vec<T>::Vec(unsafe_bitcopy_t, const Vec &bits) noexcept : repr(bits.repr) {} +#endif // CXXBRIDGE1_RUST_VEC + +#ifndef CXXBRIDGE1_IS_COMPLETE +#define CXXBRIDGE1_IS_COMPLETE +namespace detail { +namespace { +template <typename T, typename = std::size_t> +struct is_complete : std::false_type {}; +template <typename T> +struct is_complete<T, decltype(sizeof(T))> : std::true_type {}; +} // namespace +} // namespace detail +#endif // CXXBRIDGE1_IS_COMPLETE + +#ifndef CXXBRIDGE1_LAYOUT +#define CXXBRIDGE1_LAYOUT +class layout { + template <typename T> + friend std::size_t size_of(); + template <typename T> + friend std::size_t align_of(); + template <typename T> + static typename std::enable_if<std::is_base_of<Opaque, T>::value, + std::size_t>::type + do_size_of() { + return T::layout::size(); + } + template <typename T> + static typename std::enable_if<!std::is_base_of<Opaque, T>::value, + std::size_t>::type + do_size_of() { + return sizeof(T); + } + template <typename T> + static + typename std::enable_if<detail::is_complete<T>::value, std::size_t>::type + size_of() { + return do_size_of<T>(); + } + template <typename T> + static typename std::enable_if<std::is_base_of<Opaque, T>::value, + std::size_t>::type + do_align_of() { + return T::layout::align(); + } + template <typename T> + static typename std::enable_if<!std::is_base_of<Opaque, T>::value, + std::size_t>::type + do_align_of() { + return alignof(T); + } + template <typename T> + static + typename std::enable_if<detail::is_complete<T>::value, std::size_t>::type + align_of() { + return do_align_of<T>(); + } +}; + +template <typename T> +std::size_t size_of() { + return layout::size_of<T>(); +} + +template <typename T> +std::size_t align_of() { + return layout::align_of<T>(); +} +#endif // CXXBRIDGE1_LAYOUT + +#ifndef CXXBRIDGE1_RELOCATABLE +#define CXXBRIDGE1_RELOCATABLE +namespace detail { +template <typename... Ts> +struct make_void { + using type = void; +}; + +template <typename... Ts> +using void_t = typename make_void<Ts...>::type; + +template <typename Void, template <typename...> class, typename...> +struct detect : std::false_type {}; +template <template <typename...> class T, typename... A> +struct detect<void_t<T<A...>>, T, A...> : std::true_type {}; + +template <template <typename...> class T, typename... A> +using is_detected = detect<void, T, A...>; + +template <typename T> +using detect_IsRelocatable = typename T::IsRelocatable; + +template <typename T> +struct get_IsRelocatable + : std::is_same<typename T::IsRelocatable, std::true_type> {}; +} // namespace detail + +template <typename T> +struct IsRelocatable + : std::conditional< + detail::is_detected<detail::detect_IsRelocatable, T>::value, + detail::get_IsRelocatable<T>, + std::integral_constant< + bool, std::is_trivially_move_constructible<T>::value && + std::is_trivially_destructible<T>::value>>::type {}; +#endif // CXXBRIDGE1_RELOCATABLE + +} // namespace cxxbridge1 +} // namespace rust diff --git a/vendor/cxx/src/c_char.rs b/vendor/cxx/src/c_char.rs new file mode 100644 index 000000000..333d8491c --- /dev/null +++ b/vendor/cxx/src/c_char.rs @@ -0,0 +1,69 @@ +#[allow(missing_docs)] +pub type c_char = c_char_definition::c_char; + +// Validate that our definition is consistent with libstd's definition, without +// introducing a dependency on libstd in ordinary builds. +#[cfg(all(test, feature = "std"))] +const _: self::c_char = 0 as std::os::raw::c_char; + +#[allow(dead_code)] +mod c_char_definition { + // These are the targets on which c_char is unsigned. + #[cfg(any( + all( + target_os = "linux", + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "hexagon", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "s390x", + target_arch = "riscv64", + target_arch = "riscv32" + ) + ), + all( + target_os = "android", + any(target_arch = "aarch64", target_arch = "arm") + ), + all(target_os = "l4re", target_arch = "x86_64"), + all( + target_os = "freebsd", + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "riscv64" + ) + ), + all( + target_os = "netbsd", + any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc") + ), + all(target_os = "openbsd", target_arch = "aarch64"), + all( + target_os = "vxworks", + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "powerpc64", + target_arch = "powerpc" + ) + ), + all(target_os = "fuchsia", target_arch = "aarch64") + ))] + pub use self::unsigned::c_char; + + // On every other target, c_char is signed. + pub use self::signed::*; + + mod unsigned { + pub type c_char = u8; + } + + mod signed { + pub type c_char = i8; + } +} diff --git a/vendor/cxx/src/cxx.cc b/vendor/cxx/src/cxx.cc new file mode 100644 index 000000000..4958eb08b --- /dev/null +++ b/vendor/cxx/src/cxx.cc @@ -0,0 +1,793 @@ +#include "../include/cxx.h" +#include <cstring> +#include <iostream> +#include <memory> + +extern "C" { +void cxxbridge1$cxx_string$init(std::string *s, const std::uint8_t *ptr, + std::size_t len) noexcept { + new (s) std::string(reinterpret_cast<const char *>(ptr), len); +} + +void cxxbridge1$cxx_string$destroy(std::string *s) noexcept { + using std::string; + s->~string(); +} + +const char *cxxbridge1$cxx_string$data(const std::string &s) noexcept { + return s.data(); +} + +std::size_t cxxbridge1$cxx_string$length(const std::string &s) noexcept { + return s.length(); +} + +void cxxbridge1$cxx_string$clear(std::string &s) noexcept { s.clear(); } + +void cxxbridge1$cxx_string$reserve_total(std::string &s, + size_t new_cap) noexcept { + s.reserve(new_cap); +} + +void cxxbridge1$cxx_string$push(std::string &s, const std::uint8_t *ptr, + std::size_t len) noexcept { + s.append(reinterpret_cast<const char *>(ptr), len); +} + +// rust::String +void cxxbridge1$string$new(rust::String *self) noexcept; +void cxxbridge1$string$clone(rust::String *self, + const rust::String &other) noexcept; +bool cxxbridge1$string$from_utf8(rust::String *self, const char *ptr, + std::size_t len) noexcept; +void cxxbridge1$string$from_utf8_lossy(rust::String *self, const char *ptr, + std::size_t len) noexcept; +bool cxxbridge1$string$from_utf16(rust::String *self, const char16_t *ptr, + std::size_t len) noexcept; +void cxxbridge1$string$from_utf16_lossy(rust::String *self, const char16_t *ptr, + std::size_t len) noexcept; +void cxxbridge1$string$drop(rust::String *self) noexcept; +const char *cxxbridge1$string$ptr(const rust::String *self) noexcept; +std::size_t cxxbridge1$string$len(const rust::String *self) noexcept; +std::size_t cxxbridge1$string$capacity(const rust::String *self) noexcept; +void cxxbridge1$string$reserve_additional(rust::String *self, + size_t additional) noexcept; +void cxxbridge1$string$reserve_total(rust::String *self, + size_t new_cap) noexcept; + +// rust::Str +void cxxbridge1$str$new(rust::Str *self) noexcept; +void cxxbridge1$str$ref(rust::Str *self, const rust::String *string) noexcept; +bool cxxbridge1$str$from(rust::Str *self, const char *ptr, + std::size_t len) noexcept; +const char *cxxbridge1$str$ptr(const rust::Str *self) noexcept; +std::size_t cxxbridge1$str$len(const rust::Str *self) noexcept; + +// rust::Slice +void cxxbridge1$slice$new(void *self, const void *ptr, + std::size_t len) noexcept; +void *cxxbridge1$slice$ptr(const void *self) noexcept; +std::size_t cxxbridge1$slice$len(const void *self) noexcept; +} // extern "C" + +namespace rust { +inline namespace cxxbridge1 { + +template <typename Exception> +void panic [[noreturn]] (const char *msg) { +#if defined(RUST_CXX_NO_EXCEPTIONS) + std::cerr << "Error: " << msg << ". Aborting." << std::endl; + std::terminate(); +#else + throw Exception(msg); +#endif +} + +template void panic<std::out_of_range> [[noreturn]] (const char *msg); + +template <typename T> +static bool is_aligned(const void *ptr) noexcept { + auto iptr = reinterpret_cast<std::uintptr_t>(ptr); + return !(iptr % alignof(T)); +} + +String::String() noexcept { cxxbridge1$string$new(this); } + +String::String(const String &other) noexcept { + cxxbridge1$string$clone(this, other); +} + +String::String(String &&other) noexcept : repr(other.repr) { + cxxbridge1$string$new(&other); +} + +String::~String() noexcept { cxxbridge1$string$drop(this); } + +static void initString(String *self, const char *s, std::size_t len) { + if (!cxxbridge1$string$from_utf8(self, s, len)) { + panic<std::invalid_argument>("data for rust::String is not utf-8"); + } +} + +static void initString(String *self, const char16_t *s, std::size_t len) { + if (!cxxbridge1$string$from_utf16(self, s, len)) { + panic<std::invalid_argument>("data for rust::String is not utf-16"); + } +} + +String::String(const std::string &s) { initString(this, s.data(), s.length()); } + +String::String(const char *s) { + assert(s != nullptr); + initString(this, s, std::strlen(s)); +} + +String::String(const char *s, std::size_t len) { + assert(s != nullptr || len == 0); + initString(this, + s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s, + len); +} + +String::String(const char16_t *s) { + assert(s != nullptr); + assert(is_aligned<char16_t>(s)); + initString(this, s, std::char_traits<char16_t>::length(s)); +} + +String::String(const char16_t *s, std::size_t len) { + assert(s != nullptr || len == 0); + assert(is_aligned<char16_t>(s)); + initString(this, + s == nullptr && len == 0 ? reinterpret_cast<const char16_t *>(2) + : s, + len); +} + +struct String::lossy_t {}; + +String::String(lossy_t, const char *s, std::size_t len) noexcept { + cxxbridge1$string$from_utf8_lossy( + this, s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s, + len); +} + +String::String(lossy_t, const char16_t *s, std::size_t len) noexcept { + cxxbridge1$string$from_utf16_lossy( + this, + s == nullptr && len == 0 ? reinterpret_cast<const char16_t *>(2) : s, + len); +} + +String String::lossy(const std::string &s) noexcept { + return String::lossy(s.data(), s.length()); +} + +String String::lossy(const char *s) noexcept { + assert(s != nullptr); + return String::lossy(s, std::strlen(s)); +} + +String String::lossy(const char *s, std::size_t len) noexcept { + assert(s != nullptr || len == 0); + return String(lossy_t{}, s, len); +} + +String String::lossy(const char16_t *s) noexcept { + assert(s != nullptr); + assert(is_aligned<char16_t>(s)); + return String(lossy_t{}, s, std::char_traits<char16_t>::length(s)); +} + +String String::lossy(const char16_t *s, std::size_t len) noexcept { + assert(s != nullptr || len == 0); + assert(is_aligned<char16_t>(s)); + return String(lossy_t{}, s, len); +} + +String &String::operator=(const String &other) &noexcept { + if (this != &other) { + cxxbridge1$string$drop(this); + cxxbridge1$string$clone(this, other); + } + return *this; +} + +String &String::operator=(String &&other) &noexcept { + cxxbridge1$string$drop(this); + this->repr = other.repr; + cxxbridge1$string$new(&other); + return *this; +} + +String::operator std::string() const { + return std::string(this->data(), this->size()); +} + +const char *String::data() const noexcept { + return cxxbridge1$string$ptr(this); +} + +std::size_t String::size() const noexcept { + return cxxbridge1$string$len(this); +} + +std::size_t String::length() const noexcept { + return cxxbridge1$string$len(this); +} + +bool String::empty() const noexcept { return this->size() == 0; } + +const char *String::c_str() noexcept { + auto len = this->length(); + cxxbridge1$string$reserve_additional(this, 1); + auto ptr = this->data(); + const_cast<char *>(ptr)[len] = '\0'; + return ptr; +} + +std::size_t String::capacity() const noexcept { + return cxxbridge1$string$capacity(this); +} + +void String::reserve(std::size_t new_cap) noexcept { + cxxbridge1$string$reserve_total(this, new_cap); +} + +String::iterator String::begin() noexcept { + return const_cast<char *>(this->data()); +} + +String::iterator String::end() noexcept { + return const_cast<char *>(this->data()) + this->size(); +} + +String::const_iterator String::begin() const noexcept { return this->cbegin(); } + +String::const_iterator String::end() const noexcept { return this->cend(); } + +String::const_iterator String::cbegin() const noexcept { return this->data(); } + +String::const_iterator String::cend() const noexcept { + return this->data() + this->size(); +} + +bool String::operator==(const String &rhs) const noexcept { + return rust::Str(*this) == rust::Str(rhs); +} + +bool String::operator!=(const String &rhs) const noexcept { + return rust::Str(*this) != rust::Str(rhs); +} + +bool String::operator<(const String &rhs) const noexcept { + return rust::Str(*this) < rust::Str(rhs); +} + +bool String::operator<=(const String &rhs) const noexcept { + return rust::Str(*this) <= rust::Str(rhs); +} + +bool String::operator>(const String &rhs) const noexcept { + return rust::Str(*this) > rust::Str(rhs); +} + +bool String::operator>=(const String &rhs) const noexcept { + return rust::Str(*this) >= rust::Str(rhs); +} + +void String::swap(String &rhs) noexcept { + using std::swap; + swap(this->repr, rhs.repr); +} + +String::String(unsafe_bitcopy_t, const String &bits) noexcept + : repr(bits.repr) {} + +std::ostream &operator<<(std::ostream &os, const String &s) { + os.write(s.data(), s.size()); + return os; +} + +Str::Str() noexcept { cxxbridge1$str$new(this); } + +Str::Str(const String &s) noexcept { cxxbridge1$str$ref(this, &s); } + +static void initStr(Str *self, const char *ptr, std::size_t len) { + if (!cxxbridge1$str$from(self, ptr, len)) { + panic<std::invalid_argument>("data for rust::Str is not utf-8"); + } +} + +Str::Str(const std::string &s) { initStr(this, s.data(), s.length()); } + +Str::Str(const char *s) { + assert(s != nullptr); + initStr(this, s, std::strlen(s)); +} + +Str::Str(const char *s, std::size_t len) { + assert(s != nullptr || len == 0); + initStr(this, + s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s, + len); +} + +Str::operator std::string() const { + return std::string(this->data(), this->size()); +} + +const char *Str::data() const noexcept { return cxxbridge1$str$ptr(this); } + +std::size_t Str::size() const noexcept { return cxxbridge1$str$len(this); } + +std::size_t Str::length() const noexcept { return this->size(); } + +bool Str::empty() const noexcept { return this->size() == 0; } + +Str::const_iterator Str::begin() const noexcept { return this->cbegin(); } + +Str::const_iterator Str::end() const noexcept { return this->cend(); } + +Str::const_iterator Str::cbegin() const noexcept { return this->data(); } + +Str::const_iterator Str::cend() const noexcept { + return this->data() + this->size(); +} + +bool Str::operator==(const Str &rhs) const noexcept { + return this->size() == rhs.size() && + std::equal(this->begin(), this->end(), rhs.begin()); +} + +bool Str::operator!=(const Str &rhs) const noexcept { return !(*this == rhs); } + +bool Str::operator<(const Str &rhs) const noexcept { + return std::lexicographical_compare(this->begin(), this->end(), rhs.begin(), + rhs.end()); +} + +bool Str::operator<=(const Str &rhs) const noexcept { + // std::mismatch(this->begin(), this->end(), rhs.begin(), rhs.end()), except + // without Undefined Behavior on C++11 if rhs is shorter than *this. + const_iterator liter = this->begin(), lend = this->end(), riter = rhs.begin(), + rend = rhs.end(); + while (liter != lend && riter != rend && *liter == *riter) { + ++liter, ++riter; + } + if (liter == lend) { + return true; // equal or *this is a prefix of rhs + } else if (riter == rend) { + return false; // rhs is a prefix of *this + } else { + return *liter <= *riter; + } +} + +bool Str::operator>(const Str &rhs) const noexcept { return rhs < *this; } + +bool Str::operator>=(const Str &rhs) const noexcept { return rhs <= *this; } + +void Str::swap(Str &rhs) noexcept { + using std::swap; + swap(this->repr, rhs.repr); +} + +std::ostream &operator<<(std::ostream &os, const Str &s) { + os.write(s.data(), s.size()); + return os; +} + +void sliceInit(void *self, const void *ptr, std::size_t len) noexcept { + cxxbridge1$slice$new(self, ptr, len); +} + +void *slicePtr(const void *self) noexcept { return cxxbridge1$slice$ptr(self); } + +std::size_t sliceLen(const void *self) noexcept { + return cxxbridge1$slice$len(self); +} + +// Rust specifies that usize is ABI compatible with C's uintptr_t. +// https://rust-lang.github.io/unsafe-code-guidelines/layout/scalars.html#isize-and-usize +// However there is no direct Rust equivalent for size_t. C does not guarantee +// that size_t and uintptr_t are compatible. In practice though, on all +// platforms supported by Rust, they are identical for ABI purposes. See the +// libc crate which unconditionally defines libc::size_t = usize. We expect the +// same here and these assertions are just here to explicitly document that. +// *Note that no assumption is made about C++ name mangling of signatures +// containing these types, not here nor anywhere in CXX.* +static_assert(sizeof(std::size_t) == sizeof(std::uintptr_t), + "unsupported size_t size"); +static_assert(alignof(std::size_t) == alignof(std::uintptr_t), + "unsupported size_t alignment"); +static_assert(sizeof(rust::isize) == sizeof(std::intptr_t), + "unsupported ssize_t size"); +static_assert(alignof(rust::isize) == alignof(std::intptr_t), + "unsupported ssize_t alignment"); + +static_assert(std::is_trivially_copy_constructible<Str>::value, + "trivial Str(const Str &)"); +static_assert(std::is_trivially_copy_assignable<Str>::value, + "trivial operator=(const Str &)"); +static_assert(std::is_trivially_destructible<Str>::value, "trivial ~Str()"); + +static_assert( + std::is_trivially_copy_constructible<Slice<const std::uint8_t>>::value, + "trivial Slice(const Slice &)"); +static_assert( + std::is_trivially_move_constructible<Slice<const std::uint8_t>>::value, + "trivial Slice(Slice &&)"); +static_assert( + std::is_trivially_copy_assignable<Slice<const std::uint8_t>>::value, + "trivial Slice::operator=(const Slice &) for const slices"); +static_assert( + std::is_trivially_move_assignable<Slice<const std::uint8_t>>::value, + "trivial Slice::operator=(Slice &&)"); +static_assert(std::is_trivially_destructible<Slice<const std::uint8_t>>::value, + "trivial ~Slice()"); + +static_assert(std::is_trivially_copy_constructible<Slice<std::uint8_t>>::value, + "trivial Slice(const Slice &)"); +static_assert(std::is_trivially_move_constructible<Slice<std::uint8_t>>::value, + "trivial Slice(Slice &&)"); +static_assert(!std::is_copy_assignable<Slice<std::uint8_t>>::value, + "delete Slice::operator=(const Slice &) for mut slices"); +static_assert(std::is_trivially_move_assignable<Slice<std::uint8_t>>::value, + "trivial Slice::operator=(Slice &&)"); +static_assert(std::is_trivially_destructible<Slice<std::uint8_t>>::value, + "trivial ~Slice()"); + +static_assert(std::is_same<Vec<std::uint8_t>::const_iterator, + Vec<const std::uint8_t>::iterator>::value, + "Vec<T>::const_iterator == Vec<const T>::iterator"); +static_assert(std::is_same<Vec<const std::uint8_t>::const_iterator, + Vec<const std::uint8_t>::iterator>::value, + "Vec<const T>::const_iterator == Vec<const T>::iterator"); +static_assert(!std::is_same<Vec<std::uint8_t>::const_iterator, + Vec<std::uint8_t>::iterator>::value, + "Vec<T>::const_iterator != Vec<T>::iterator"); + +static const char *errorCopy(const char *ptr, std::size_t len) { + char *copy = new char[len]; + std::memcpy(copy, ptr, len); + return copy; +} + +extern "C" { +const char *cxxbridge1$error(const char *ptr, std::size_t len) noexcept { + return errorCopy(ptr, len); +} +} // extern "C" + +Error::Error(const Error &other) + : std::exception(other), + msg(other.msg ? errorCopy(other.msg, other.len) : nullptr), + len(other.len) {} + +Error::Error(Error &&other) noexcept + : std::exception(std::move(other)), msg(other.msg), len(other.len) { + other.msg = nullptr; + other.len = 0; +} + +Error::~Error() noexcept { delete[] this->msg; } + +Error &Error::operator=(const Error &other) & { + if (this != &other) { + std::exception::operator=(other); + delete[] this->msg; + this->msg = nullptr; + if (other.msg) { + this->msg = errorCopy(other.msg, other.len); + this->len = other.len; + } + } + return *this; +} + +Error &Error::operator=(Error &&other) &noexcept { + std::exception::operator=(std::move(other)); + delete[] this->msg; + this->msg = other.msg; + this->len = other.len; + other.msg = nullptr; + other.len = 0; + return *this; +} + +const char *Error::what() const noexcept { return this->msg; } + +namespace { +template <typename T> +union MaybeUninit { + T value; + MaybeUninit() {} + ~MaybeUninit() {} +}; +} // namespace + +namespace repr { +struct PtrLen final { + void *ptr; + std::size_t len; +}; +} // namespace repr + +extern "C" { +repr::PtrLen cxxbridge1$exception(const char *, std::size_t len) noexcept; +} + +namespace detail { +// On some platforms size_t is the same C++ type as one of the sized integer +// types; on others it is a distinct type. Only in the latter case do we need to +// define a specialized impl of rust::Vec<size_t>, because in the former case it +// would collide with one of the other specializations. +using usize_if_unique = + typename std::conditional<std::is_same<size_t, uint64_t>::value || + std::is_same<size_t, uint32_t>::value, + struct usize_ignore, size_t>::type; +using isize_if_unique = + typename std::conditional<std::is_same<rust::isize, int64_t>::value || + std::is_same<rust::isize, int32_t>::value, + struct isize_ignore, rust::isize>::type; + +class Fail final { + repr::PtrLen &throw$; + +public: + Fail(repr::PtrLen &throw$) noexcept : throw$(throw$) {} + void operator()(const char *) noexcept; + void operator()(const std::string &) noexcept; +}; + +void Fail::operator()(const char *catch$) noexcept { + throw$ = cxxbridge1$exception(catch$, std::strlen(catch$)); +} + +void Fail::operator()(const std::string &catch$) noexcept { + throw$ = cxxbridge1$exception(catch$.data(), catch$.length()); +} +} // namespace detail + +} // namespace cxxbridge1 +} // namespace rust + +namespace { +template <typename T> +void destroy(T *ptr) { + ptr->~T(); +} +} // namespace + +extern "C" { +void cxxbridge1$unique_ptr$std$string$null( + std::unique_ptr<std::string> *ptr) noexcept { + new (ptr) std::unique_ptr<std::string>(); +} +void cxxbridge1$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr, + std::string *raw) noexcept { + new (ptr) std::unique_ptr<std::string>(raw); +} +const std::string *cxxbridge1$unique_ptr$std$string$get( + const std::unique_ptr<std::string> &ptr) noexcept { + return ptr.get(); +} +std::string *cxxbridge1$unique_ptr$std$string$release( + std::unique_ptr<std::string> &ptr) noexcept { + return ptr.release(); +} +void cxxbridge1$unique_ptr$std$string$drop( + std::unique_ptr<std::string> *ptr) noexcept { + ptr->~unique_ptr(); +} +} // extern "C" + +namespace { +const std::size_t kMaxExpectedWordsInString = 8; +static_assert(alignof(std::string) <= alignof(void *), + "unexpectedly large std::string alignment"); +static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *), + "unexpectedly large std::string size"); +} // namespace + +#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE) \ + std::size_t cxxbridge1$std$vector$##RUST_TYPE##$size( \ + const std::vector<CXX_TYPE> &s) noexcept { \ + return s.size(); \ + } \ + CXX_TYPE *cxxbridge1$std$vector$##RUST_TYPE##$get_unchecked( \ + std::vector<CXX_TYPE> *s, std::size_t pos) noexcept { \ + return &(*s)[pos]; \ + } \ + void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$null( \ + std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \ + new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(); \ + } \ + void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$raw( \ + std::unique_ptr<std::vector<CXX_TYPE>> *ptr, \ + std::vector<CXX_TYPE> *raw) noexcept { \ + new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw); \ + } \ + const std::vector<CXX_TYPE> \ + *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$get( \ + const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \ + return ptr.get(); \ + } \ + std::vector<CXX_TYPE> \ + *cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$release( \ + std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept { \ + return ptr.release(); \ + } \ + void cxxbridge1$unique_ptr$std$vector$##RUST_TYPE##$drop( \ + std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept { \ + ptr->~unique_ptr(); \ + } + +#define STD_VECTOR_TRIVIAL_OPS(RUST_TYPE, CXX_TYPE) \ + void cxxbridge1$std$vector$##RUST_TYPE##$push_back( \ + std::vector<CXX_TYPE> *v, CXX_TYPE *value) noexcept { \ + v->push_back(std::move(*value)); \ + destroy(value); \ + } \ + void cxxbridge1$std$vector$##RUST_TYPE##$pop_back(std::vector<CXX_TYPE> *v, \ + CXX_TYPE *out) noexcept { \ + new (out) CXX_TYPE(std::move(v->back())); \ + v->pop_back(); \ + } + +#define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE) \ + void cxxbridge1$rust_vec$##RUST_TYPE##$new( \ + rust::Vec<CXX_TYPE> *ptr) noexcept; \ + void cxxbridge1$rust_vec$##RUST_TYPE##$drop( \ + rust::Vec<CXX_TYPE> *ptr) noexcept; \ + std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$len( \ + const rust::Vec<CXX_TYPE> *ptr) noexcept; \ + std::size_t cxxbridge1$rust_vec$##RUST_TYPE##$capacity( \ + const rust::Vec<CXX_TYPE> *ptr) noexcept; \ + const CXX_TYPE *cxxbridge1$rust_vec$##RUST_TYPE##$data( \ + const rust::Vec<CXX_TYPE> *ptr) noexcept; \ + void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total( \ + rust::Vec<CXX_TYPE> *ptr, std::size_t new_cap) noexcept; \ + void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr, \ + std::size_t len) noexcept; \ + void cxxbridge1$rust_vec$##RUST_TYPE##$truncate(rust::Vec<CXX_TYPE> *ptr, \ + std::size_t len) noexcept; + +#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \ + template <> \ + Vec<CXX_TYPE>::Vec() noexcept { \ + cxxbridge1$rust_vec$##RUST_TYPE##$new(this); \ + } \ + template <> \ + void Vec<CXX_TYPE>::drop() noexcept { \ + return cxxbridge1$rust_vec$##RUST_TYPE##$drop(this); \ + } \ + template <> \ + std::size_t Vec<CXX_TYPE>::size() const noexcept { \ + return cxxbridge1$rust_vec$##RUST_TYPE##$len(this); \ + } \ + template <> \ + std::size_t Vec<CXX_TYPE>::capacity() const noexcept { \ + return cxxbridge1$rust_vec$##RUST_TYPE##$capacity(this); \ + } \ + template <> \ + const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept { \ + return cxxbridge1$rust_vec$##RUST_TYPE##$data(this); \ + } \ + template <> \ + void Vec<CXX_TYPE>::reserve_total(std::size_t new_cap) noexcept { \ + cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total(this, new_cap); \ + } \ + template <> \ + void Vec<CXX_TYPE>::set_len(std::size_t len) noexcept { \ + cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len); \ + } \ + template <> \ + void Vec<CXX_TYPE>::truncate(std::size_t len) { \ + cxxbridge1$rust_vec$##RUST_TYPE##$truncate(this, len); \ + } + +#define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE) \ + static_assert(sizeof(std::shared_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \ + static_assert(alignof(std::shared_ptr<CXX_TYPE>) == alignof(void *), ""); \ + void cxxbridge1$std$shared_ptr$##RUST_TYPE##$null( \ + std::shared_ptr<CXX_TYPE> *ptr) noexcept { \ + new (ptr) std::shared_ptr<CXX_TYPE>(); \ + } \ + CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$uninit( \ + std::shared_ptr<CXX_TYPE> *ptr) noexcept { \ + CXX_TYPE *uninit = \ + reinterpret_cast<CXX_TYPE *>(new rust::MaybeUninit<CXX_TYPE>); \ + new (ptr) std::shared_ptr<CXX_TYPE>(uninit); \ + return uninit; \ + } \ + void cxxbridge1$std$shared_ptr$##RUST_TYPE##$clone( \ + const std::shared_ptr<CXX_TYPE> &self, \ + std::shared_ptr<CXX_TYPE> *ptr) noexcept { \ + new (ptr) std::shared_ptr<CXX_TYPE>(self); \ + } \ + const CXX_TYPE *cxxbridge1$std$shared_ptr$##RUST_TYPE##$get( \ + const std::shared_ptr<CXX_TYPE> &self) noexcept { \ + return self.get(); \ + } \ + void cxxbridge1$std$shared_ptr$##RUST_TYPE##$drop( \ + const std::shared_ptr<CXX_TYPE> *self) noexcept { \ + self->~shared_ptr(); \ + } \ + static_assert(sizeof(std::weak_ptr<CXX_TYPE>) == 2 * sizeof(void *), ""); \ + static_assert(alignof(std::weak_ptr<CXX_TYPE>) == alignof(void *), ""); \ + void cxxbridge1$std$weak_ptr$##RUST_TYPE##$null( \ + std::weak_ptr<CXX_TYPE> *ptr) noexcept { \ + new (ptr) std::weak_ptr<CXX_TYPE>(); \ + } \ + void cxxbridge1$std$weak_ptr$##RUST_TYPE##$clone( \ + const std::weak_ptr<CXX_TYPE> &self, \ + std::weak_ptr<CXX_TYPE> *ptr) noexcept { \ + new (ptr) std::weak_ptr<CXX_TYPE>(self); \ + } \ + void cxxbridge1$std$weak_ptr$##RUST_TYPE##$downgrade( \ + const std::shared_ptr<CXX_TYPE> &shared, \ + std::weak_ptr<CXX_TYPE> *weak) noexcept { \ + new (weak) std::weak_ptr<CXX_TYPE>(shared); \ + } \ + void cxxbridge1$std$weak_ptr$##RUST_TYPE##$upgrade( \ + const std::weak_ptr<CXX_TYPE> &weak, \ + std::shared_ptr<CXX_TYPE> *shared) noexcept { \ + new (shared) std::shared_ptr<CXX_TYPE>(weak.lock()); \ + } \ + void cxxbridge1$std$weak_ptr$##RUST_TYPE##$drop( \ + const std::weak_ptr<CXX_TYPE> *self) noexcept { \ + self->~weak_ptr(); \ + } + +// Usize and isize are the same type as one of the below. +#define FOR_EACH_NUMERIC(MACRO) \ + MACRO(u8, std::uint8_t) \ + MACRO(u16, std::uint16_t) \ + MACRO(u32, std::uint32_t) \ + MACRO(u64, std::uint64_t) \ + MACRO(i8, std::int8_t) \ + MACRO(i16, std::int16_t) \ + MACRO(i32, std::int32_t) \ + MACRO(i64, std::int64_t) \ + MACRO(f32, float) \ + MACRO(f64, double) + +#define FOR_EACH_TRIVIAL_STD_VECTOR(MACRO) \ + FOR_EACH_NUMERIC(MACRO) \ + MACRO(usize, std::size_t) \ + MACRO(isize, rust::isize) + +#define FOR_EACH_STD_VECTOR(MACRO) \ + FOR_EACH_TRIVIAL_STD_VECTOR(MACRO) \ + MACRO(string, std::string) + +#define FOR_EACH_RUST_VEC(MACRO) \ + FOR_EACH_NUMERIC(MACRO) \ + MACRO(bool, bool) \ + MACRO(char, char) \ + MACRO(usize, rust::detail::usize_if_unique) \ + MACRO(isize, rust::detail::isize_if_unique) \ + MACRO(string, rust::String) \ + MACRO(str, rust::Str) + +#define FOR_EACH_SHARED_PTR(MACRO) \ + FOR_EACH_NUMERIC(MACRO) \ + MACRO(bool, bool) \ + MACRO(usize, std::size_t) \ + MACRO(isize, rust::isize) \ + MACRO(string, std::string) + +extern "C" { +FOR_EACH_STD_VECTOR(STD_VECTOR_OPS) +FOR_EACH_TRIVIAL_STD_VECTOR(STD_VECTOR_TRIVIAL_OPS) +FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS) +FOR_EACH_SHARED_PTR(SHARED_PTR_OPS) +} // extern "C" + +namespace rust { +inline namespace cxxbridge1 { +FOR_EACH_RUST_VEC(RUST_VEC_OPS) +} // namespace cxxbridge1 +} // namespace rust diff --git a/vendor/cxx/src/cxx_string.rs b/vendor/cxx/src/cxx_string.rs new file mode 100644 index 000000000..d5d0af4a4 --- /dev/null +++ b/vendor/cxx/src/cxx_string.rs @@ -0,0 +1,312 @@ +use crate::actually_private::Private; +use crate::lossy; +#[cfg(feature = "alloc")] +use alloc::borrow::Cow; +#[cfg(feature = "alloc")] +use alloc::string::String; +use core::cmp::Ordering; +use core::fmt::{self, Debug, Display}; +use core::hash::{Hash, Hasher}; +use core::marker::{PhantomData, PhantomPinned}; +use core::mem::MaybeUninit; +use core::pin::Pin; +use core::slice; +use core::str::{self, Utf8Error}; + +extern "C" { + #[link_name = "cxxbridge1$cxx_string$init"] + fn string_init(this: &mut MaybeUninit<CxxString>, ptr: *const u8, len: usize); + #[link_name = "cxxbridge1$cxx_string$destroy"] + fn string_destroy(this: &mut MaybeUninit<CxxString>); + #[link_name = "cxxbridge1$cxx_string$data"] + fn string_data(this: &CxxString) -> *const u8; + #[link_name = "cxxbridge1$cxx_string$length"] + fn string_length(this: &CxxString) -> usize; + #[link_name = "cxxbridge1$cxx_string$clear"] + fn string_clear(this: Pin<&mut CxxString>); + #[link_name = "cxxbridge1$cxx_string$reserve_total"] + fn string_reserve_total(this: Pin<&mut CxxString>, new_cap: usize); + #[link_name = "cxxbridge1$cxx_string$push"] + fn string_push(this: Pin<&mut CxxString>, ptr: *const u8, len: usize); +} + +/// Binding to C++ `std::string`. +/// +/// # Invariants +/// +/// As an invariant of this API and the static analysis of the cxx::bridge +/// macro, in Rust code we can never obtain a `CxxString` by value. C++'s string +/// requires a move constructor and may hold internal pointers, which is not +/// compatible with Rust's move behavior. Instead in Rust code we will only ever +/// look at a CxxString through a reference or smart pointer, as in `&CxxString` +/// or `UniquePtr<CxxString>`. +#[repr(C)] +pub struct CxxString { + _private: [u8; 0], + _pinned: PhantomData<PhantomPinned>, +} + +/// Construct a C++ std::string on the Rust stack. +/// +/// # Syntax +/// +/// In statement position: +/// +/// ``` +/// # use cxx::let_cxx_string; +/// # let expression = ""; +/// let_cxx_string!(var = expression); +/// ``` +/// +/// The `expression` may have any type that implements `AsRef<[u8]>`. Commonly +/// it will be a string literal, but for example `&[u8]` and `String` would work +/// as well. +/// +/// The macro expands to something resembling `let $var: Pin<&mut CxxString> = +/// /*???*/;`. The resulting [`Pin`] can be deref'd to `&CxxString` as needed. +/// +/// # Example +/// +/// ``` +/// use cxx::{let_cxx_string, CxxString}; +/// +/// fn f(s: &CxxString) {/* ... */} +/// +/// fn main() { +/// let_cxx_string!(s = "example"); +/// f(&s); +/// } +/// ``` +#[macro_export] +macro_rules! let_cxx_string { + ($var:ident = $value:expr $(,)?) => { + let mut cxx_stack_string = $crate::private::StackString::new(); + #[allow(unused_mut, unused_unsafe)] + let mut $var = match $value { + let_cxx_string => unsafe { cxx_stack_string.init(let_cxx_string) }, + }; + }; +} + +impl CxxString { + /// `CxxString` is not constructible via `new`. Instead, use the + /// [`let_cxx_string!`] macro. + pub fn new<T: Private>() -> Self { + unreachable!() + } + + /// Returns the length of the string in bytes. + /// + /// Matches the behavior of C++ [std::string::size][size]. + /// + /// [size]: https://en.cppreference.com/w/cpp/string/basic_string/size + pub fn len(&self) -> usize { + unsafe { string_length(self) } + } + + /// Returns true if `self` has a length of zero bytes. + /// + /// Matches the behavior of C++ [std::string::empty][empty]. + /// + /// [empty]: https://en.cppreference.com/w/cpp/string/basic_string/empty + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Returns a byte slice of this string's contents. + pub fn as_bytes(&self) -> &[u8] { + let data = self.as_ptr(); + let len = self.len(); + unsafe { slice::from_raw_parts(data, len) } + } + + /// Produces a pointer to the first character of the string. + /// + /// Matches the behavior of C++ [std::string::data][data]. + /// + /// Note that the return type may look like `const char *` but is not a + /// `const char *` in the typical C sense, as C++ strings may contain + /// internal null bytes. As such, the returned pointer only makes sense as a + /// string in combination with the length returned by [`len()`][len]. + /// + /// [data]: https://en.cppreference.com/w/cpp/string/basic_string/data + /// [len]: #method.len + pub fn as_ptr(&self) -> *const u8 { + unsafe { string_data(self) } + } + + /// Validates that the C++ string contains UTF-8 data and produces a view of + /// it as a Rust &str, otherwise an error. + pub fn to_str(&self) -> Result<&str, Utf8Error> { + str::from_utf8(self.as_bytes()) + } + + /// If the contents of the C++ string are valid UTF-8, this function returns + /// a view as a Cow::Borrowed &str. Otherwise replaces any invalid UTF-8 + /// sequences with the U+FFFD [replacement character] and returns a + /// Cow::Owned String. + /// + /// [replacement character]: https://doc.rust-lang.org/std/char/constant.REPLACEMENT_CHARACTER.html + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + pub fn to_string_lossy(&self) -> Cow<str> { + String::from_utf8_lossy(self.as_bytes()) + } + + /// Removes all characters from the string. + /// + /// Matches the behavior of C++ [std::string::clear][clear]. + /// + /// Note: **unlike** the guarantee of Rust's `std::string::String::clear`, + /// the C++ standard does not require that capacity is unchanged by this + /// operation. In practice existing implementations do not change the + /// capacity but all pointers, references, and iterators into the string + /// contents are nevertheless invalidated. + /// + /// [clear]: https://en.cppreference.com/w/cpp/string/basic_string/clear + pub fn clear(self: Pin<&mut Self>) { + unsafe { string_clear(self) } + } + + /// Ensures that this string's capacity is at least `additional` bytes + /// larger than its length. + /// + /// The capacity may be increased by more than `additional` bytes if it + /// chooses, to amortize the cost of frequent reallocations. + /// + /// **The meaning of the argument is not the same as + /// [std::string::reserve][reserve] in C++.** The C++ standard library and + /// Rust standard library both have a `reserve` method on strings, but in + /// C++ code the argument always refers to total capacity, whereas in Rust + /// code it always refers to additional capacity. This API on `CxxString` + /// follows the Rust convention, the same way that for the length accessor + /// we use the Rust conventional `len()` naming and not C++ `size()` or + /// `length()`. + /// + /// # Panics + /// + /// Panics if the new capacity overflows usize. + /// + /// [reserve]: https://en.cppreference.com/w/cpp/string/basic_string/reserve + pub fn reserve(self: Pin<&mut Self>, additional: usize) { + let new_cap = self + .len() + .checked_add(additional) + .expect("CxxString capacity overflow"); + unsafe { string_reserve_total(self, new_cap) } + } + + /// Appends a given string slice onto the end of this C++ string. + pub fn push_str(self: Pin<&mut Self>, s: &str) { + self.push_bytes(s.as_bytes()); + } + + /// Appends arbitrary bytes onto the end of this C++ string. + pub fn push_bytes(self: Pin<&mut Self>, bytes: &[u8]) { + unsafe { string_push(self, bytes.as_ptr(), bytes.len()) } + } +} + +impl Display for CxxString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + lossy::display(self.as_bytes(), f) + } +} + +impl Debug for CxxString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + lossy::debug(self.as_bytes(), f) + } +} + +impl PartialEq for CxxString { + fn eq(&self, other: &Self) -> bool { + self.as_bytes() == other.as_bytes() + } +} + +impl PartialEq<CxxString> for str { + fn eq(&self, other: &CxxString) -> bool { + self.as_bytes() == other.as_bytes() + } +} + +impl PartialEq<str> for CxxString { + fn eq(&self, other: &str) -> bool { + self.as_bytes() == other.as_bytes() + } +} + +impl Eq for CxxString {} + +impl PartialOrd for CxxString { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + self.as_bytes().partial_cmp(other.as_bytes()) + } +} + +impl Ord for CxxString { + fn cmp(&self, other: &Self) -> Ordering { + self.as_bytes().cmp(other.as_bytes()) + } +} + +impl Hash for CxxString { + fn hash<H: Hasher>(&self, state: &mut H) { + self.as_bytes().hash(state); + } +} + +impl fmt::Write for Pin<&mut CxxString> { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.as_mut().push_str(s); + Ok(()) + } +} + +#[cfg(feature = "std")] +impl std::io::Write for Pin<&mut CxxString> { + fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { + self.as_mut().push_bytes(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + +#[doc(hidden)] +#[repr(C)] +pub struct StackString { + // Static assertions in cxx.cc validate that this is large enough and + // aligned enough. + space: MaybeUninit<[usize; 8]>, +} + +#[allow(missing_docs)] +impl StackString { + pub fn new() -> Self { + StackString { + space: MaybeUninit::uninit(), + } + } + + pub unsafe fn init(&mut self, value: impl AsRef<[u8]>) -> Pin<&mut CxxString> { + let value = value.as_ref(); + unsafe { + let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>(); + string_init(this, value.as_ptr(), value.len()); + Pin::new_unchecked(&mut *this.as_mut_ptr()) + } + } +} + +impl Drop for StackString { + fn drop(&mut self) { + unsafe { + let this = &mut *self.space.as_mut_ptr().cast::<MaybeUninit<CxxString>>(); + string_destroy(this); + } + } +} diff --git a/vendor/cxx/src/cxx_vector.rs b/vendor/cxx/src/cxx_vector.rs new file mode 100644 index 000000000..abf9297a8 --- /dev/null +++ b/vendor/cxx/src/cxx_vector.rs @@ -0,0 +1,492 @@ +//! Less used details of `CxxVector` are exposed in this module. `CxxVector` +//! itself is exposed at the crate root. + +use crate::extern_type::ExternType; +use crate::kind::Trivial; +use crate::string::CxxString; +use core::ffi::c_void; +use core::fmt::{self, Debug}; +use core::iter::FusedIterator; +use core::marker::{PhantomData, PhantomPinned}; +use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::pin::Pin; +use core::slice; + +/// Binding to C++ `std::vector<T, std::allocator<T>>`. +/// +/// # Invariants +/// +/// As an invariant of this API and the static analysis of the cxx::bridge +/// macro, in Rust code we can never obtain a `CxxVector` by value. Instead in +/// Rust code we will only ever look at a vector behind a reference or smart +/// pointer, as in `&CxxVector<T>` or `UniquePtr<CxxVector<T>>`. +#[repr(C, packed)] +pub struct CxxVector<T> { + // A thing, because repr(C) structs are not allowed to consist exclusively + // of PhantomData fields. + _void: [c_void; 0], + // The conceptual vector elements to ensure that autotraits are propagated + // correctly, e.g. CxxVector is UnwindSafe iff T is. + _elements: PhantomData<[T]>, + // Prevent unpin operation from Pin<&mut CxxVector<T>> to &mut CxxVector<T>. + _pinned: PhantomData<PhantomPinned>, +} + +impl<T> CxxVector<T> +where + T: VectorElement, +{ + /// Returns the number of elements in the vector. + /// + /// Matches the behavior of C++ [std::vector\<T\>::size][size]. + /// + /// [size]: https://en.cppreference.com/w/cpp/container/vector/size + pub fn len(&self) -> usize { + T::__vector_size(self) + } + + /// Returns true if the vector contains no elements. + /// + /// Matches the behavior of C++ [std::vector\<T\>::empty][empty]. + /// + /// [empty]: https://en.cppreference.com/w/cpp/container/vector/empty + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Returns a reference to an element at the given position, or `None` if + /// out of bounds. + pub fn get(&self, pos: usize) -> Option<&T> { + if pos < self.len() { + Some(unsafe { self.get_unchecked(pos) }) + } else { + None + } + } + + /// Returns a pinned mutable reference to an element at the given position, + /// or `None` if out of bounds. + pub fn index_mut(self: Pin<&mut Self>, pos: usize) -> Option<Pin<&mut T>> { + if pos < self.len() { + Some(unsafe { self.index_unchecked_mut(pos) }) + } else { + None + } + } + + /// Returns a reference to an element without doing bounds checking. + /// + /// This is generally not recommended, use with caution! Calling this method + /// with an out-of-bounds index is undefined behavior even if the resulting + /// reference is not used. + /// + /// Matches the behavior of C++ + /// [std::vector\<T\>::operator\[\] const][operator_at]. + /// + /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at + pub unsafe fn get_unchecked(&self, pos: usize) -> &T { + let this = self as *const CxxVector<T> as *mut CxxVector<T>; + unsafe { + let ptr = T::__get_unchecked(this, pos) as *const T; + &*ptr + } + } + + /// Returns a pinned mutable reference to an element without doing bounds + /// checking. + /// + /// This is generally not recommended, use with caution! Calling this method + /// with an out-of-bounds index is undefined behavior even if the resulting + /// reference is not used. + /// + /// Matches the behavior of C++ + /// [std::vector\<T\>::operator\[\]][operator_at]. + /// + /// [operator_at]: https://en.cppreference.com/w/cpp/container/vector/operator_at + pub unsafe fn index_unchecked_mut(self: Pin<&mut Self>, pos: usize) -> Pin<&mut T> { + unsafe { + let ptr = T::__get_unchecked(self.get_unchecked_mut(), pos); + Pin::new_unchecked(&mut *ptr) + } + } + + /// Returns a slice to the underlying contiguous array of elements. + pub fn as_slice(&self) -> &[T] + where + T: ExternType<Kind = Trivial>, + { + let len = self.len(); + if len == 0 { + // The slice::from_raw_parts in the other branch requires a nonnull + // and properly aligned data ptr. C++ standard does not guarantee + // that data() on a vector with size 0 would return a nonnull + // pointer or sufficiently aligned pointer, so using it would be + // undefined behavior. Create our own empty slice in Rust instead + // which upholds the invariants. + &[] + } else { + let this = self as *const CxxVector<T> as *mut CxxVector<T>; + let ptr = unsafe { T::__get_unchecked(this, 0) }; + unsafe { slice::from_raw_parts(ptr, len) } + } + } + + /// Returns a slice to the underlying contiguous array of elements by + /// mutable reference. + pub fn as_mut_slice(self: Pin<&mut Self>) -> &mut [T] + where + T: ExternType<Kind = Trivial>, + { + let len = self.len(); + if len == 0 { + &mut [] + } else { + let ptr = unsafe { T::__get_unchecked(self.get_unchecked_mut(), 0) }; + unsafe { slice::from_raw_parts_mut(ptr, len) } + } + } + + /// Returns an iterator over elements of type `&T`. + pub fn iter(&self) -> Iter<T> { + Iter { v: self, index: 0 } + } + + /// Returns an iterator over elements of type `Pin<&mut T>`. + pub fn iter_mut(self: Pin<&mut Self>) -> IterMut<T> { + IterMut { v: self, index: 0 } + } + + /// Appends an element to the back of the vector. + /// + /// Matches the behavior of C++ [std::vector\<T\>::push_back][push_back]. + /// + /// [push_back]: https://en.cppreference.com/w/cpp/container/vector/push_back + pub fn push(self: Pin<&mut Self>, value: T) + where + T: ExternType<Kind = Trivial>, + { + let mut value = ManuallyDrop::new(value); + unsafe { + // C++ calls move constructor followed by destructor on `value`. + T::__push_back(self, &mut value); + } + } + + /// Removes the last element from a vector and returns it, or `None` if the + /// vector is empty. + pub fn pop(self: Pin<&mut Self>) -> Option<T> + where + T: ExternType<Kind = Trivial>, + { + if self.is_empty() { + None + } else { + let mut value = MaybeUninit::uninit(); + Some(unsafe { + T::__pop_back(self, &mut value); + value.assume_init() + }) + } + } +} + +/// Iterator over elements of a `CxxVector` by shared reference. +/// +/// The iterator element type is `&'a T`. +pub struct Iter<'a, T> { + v: &'a CxxVector<T>, + index: usize, +} + +impl<'a, T> IntoIterator for &'a CxxVector<T> +where + T: VectorElement, +{ + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a, T> Iterator for Iter<'a, T> +where + T: VectorElement, +{ + type Item = &'a T; + + fn next(&mut self) -> Option<Self::Item> { + let next = self.v.get(self.index)?; + self.index += 1; + Some(next) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let len = self.len(); + (len, Some(len)) + } +} + +impl<'a, T> ExactSizeIterator for Iter<'a, T> +where + T: VectorElement, +{ + fn len(&self) -> usize { + self.v.len() - self.index + } +} + +impl<'a, T> FusedIterator for Iter<'a, T> where T: VectorElement {} + +/// Iterator over elements of a `CxxVector` by pinned mutable reference. +/// +/// The iterator element type is `Pin<&'a mut T>`. +pub struct IterMut<'a, T> { + v: Pin<&'a mut CxxVector<T>>, + index: usize, +} + +impl<'a, T> IntoIterator for Pin<&'a mut CxxVector<T>> +where + T: VectorElement, +{ + type Item = Pin<&'a mut T>; + type IntoIter = IterMut<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.iter_mut() + } +} + +impl<'a, T> Iterator for IterMut<'a, T> +where + T: VectorElement, +{ + type Item = Pin<&'a mut T>; + + fn next(&mut self) -> Option<Self::Item> { + let next = self.v.as_mut().index_mut(self.index)?; + self.index += 1; + // Extend lifetime to allow simultaneous holding of nonoverlapping + // elements, analogous to slice::split_first_mut. + unsafe { + let ptr = Pin::into_inner_unchecked(next) as *mut T; + Some(Pin::new_unchecked(&mut *ptr)) + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let len = self.len(); + (len, Some(len)) + } +} + +impl<'a, T> ExactSizeIterator for IterMut<'a, T> +where + T: VectorElement, +{ + fn len(&self) -> usize { + self.v.len() - self.index + } +} + +impl<'a, T> FusedIterator for IterMut<'a, T> where T: VectorElement {} + +impl<T> Debug for CxxVector<T> +where + T: VectorElement + Debug, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.debug_list().entries(self).finish() + } +} + +/// Trait bound for types which may be used as the `T` inside of a +/// `CxxVector<T>` in generic code. +/// +/// This trait has no publicly callable or implementable methods. Implementing +/// it outside of the CXX codebase is not supported. +/// +/// # Example +/// +/// A bound `T: VectorElement` may be necessary when manipulating [`CxxVector`] +/// in generic code. +/// +/// ``` +/// use cxx::vector::{CxxVector, VectorElement}; +/// use std::fmt::Display; +/// +/// pub fn take_generic_vector<T>(vector: &CxxVector<T>) +/// where +/// T: VectorElement + Display, +/// { +/// println!("the vector elements are:"); +/// for element in vector { +/// println!(" • {}", element); +/// } +/// } +/// ``` +/// +/// Writing the same generic function without a `VectorElement` trait bound +/// would not compile. +pub unsafe trait VectorElement: Sized { + #[doc(hidden)] + fn __typename(f: &mut fmt::Formatter) -> fmt::Result; + #[doc(hidden)] + fn __vector_size(v: &CxxVector<Self>) -> usize; + #[doc(hidden)] + unsafe fn __get_unchecked(v: *mut CxxVector<Self>, pos: usize) -> *mut Self; + #[doc(hidden)] + unsafe fn __push_back(v: Pin<&mut CxxVector<Self>>, value: &mut ManuallyDrop<Self>) { + // Opaque C type vector elements do not get this method because they can + // never exist by value on the Rust side of the bridge. + let _ = v; + let _ = value; + unreachable!() + } + #[doc(hidden)] + unsafe fn __pop_back(v: Pin<&mut CxxVector<Self>>, out: &mut MaybeUninit<Self>) { + // Opaque C type vector elements do not get this method because they can + // never exist by value on the Rust side of the bridge. + let _ = v; + let _ = out; + unreachable!() + } + #[doc(hidden)] + fn __unique_ptr_null() -> MaybeUninit<*mut c_void>; + #[doc(hidden)] + unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> MaybeUninit<*mut c_void>; + #[doc(hidden)] + unsafe fn __unique_ptr_get(repr: MaybeUninit<*mut c_void>) -> *const CxxVector<Self>; + #[doc(hidden)] + unsafe fn __unique_ptr_release(repr: MaybeUninit<*mut c_void>) -> *mut CxxVector<Self>; + #[doc(hidden)] + unsafe fn __unique_ptr_drop(repr: MaybeUninit<*mut c_void>); +} + +macro_rules! vector_element_by_value_methods { + (opaque, $segment:expr, $ty:ty) => {}; + (trivial, $segment:expr, $ty:ty) => { + unsafe fn __push_back(v: Pin<&mut CxxVector<$ty>>, value: &mut ManuallyDrop<$ty>) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$push_back")] + fn __push_back(_: Pin<&mut CxxVector<$ty>>, _: &mut ManuallyDrop<$ty>); + } + } + unsafe { __push_back(v, value) } + } + unsafe fn __pop_back(v: Pin<&mut CxxVector<$ty>>, out: &mut MaybeUninit<$ty>) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$pop_back")] + fn __pop_back(_: Pin<&mut CxxVector<$ty>>, _: &mut MaybeUninit<$ty>); + } + } + unsafe { __pop_back(v, out) } + } + }; +} + +macro_rules! impl_vector_element { + ($kind:ident, $segment:expr, $name:expr, $ty:ty) => { + const_assert_eq!(0, mem::size_of::<CxxVector<$ty>>()); + const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>()); + + unsafe impl VectorElement for $ty { + fn __typename(f: &mut fmt::Formatter) -> fmt::Result { + f.write_str($name) + } + fn __vector_size(v: &CxxVector<$ty>) -> usize { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$size")] + fn __vector_size(_: &CxxVector<$ty>) -> usize; + } + } + unsafe { __vector_size(v) } + } + unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$vector$", $segment, "$get_unchecked")] + fn __get_unchecked(_: *mut CxxVector<$ty>, _: usize) -> *mut $ty; + } + } + unsafe { __get_unchecked(v, pos) } + } + vector_element_by_value_methods!($kind, $segment, $ty); + fn __unique_ptr_null() -> MaybeUninit<*mut c_void> { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$null")] + fn __unique_ptr_null(this: *mut MaybeUninit<*mut c_void>); + } + } + let mut repr = MaybeUninit::uninit(); + unsafe { __unique_ptr_null(&mut repr) } + repr + } + unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> MaybeUninit<*mut c_void> { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$raw")] + fn __unique_ptr_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxVector<$ty>); + } + } + let mut repr = MaybeUninit::uninit(); + unsafe { __unique_ptr_raw(&mut repr, raw) } + repr + } + unsafe fn __unique_ptr_get(repr: MaybeUninit<*mut c_void>) -> *const CxxVector<Self> { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$get")] + fn __unique_ptr_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxVector<$ty>; + } + } + unsafe { __unique_ptr_get(&repr) } + } + unsafe fn __unique_ptr_release(mut repr: MaybeUninit<*mut c_void>) -> *mut CxxVector<Self> { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$release")] + fn __unique_ptr_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxVector<$ty>; + } + } + unsafe { __unique_ptr_release(&mut repr) } + } + unsafe fn __unique_ptr_drop(mut repr: MaybeUninit<*mut c_void>) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$unique_ptr$std$vector$", $segment, "$drop")] + fn __unique_ptr_drop(this: *mut MaybeUninit<*mut c_void>); + } + } + unsafe { __unique_ptr_drop(&mut repr) } + } + } + }; +} + +macro_rules! impl_vector_element_for_primitive { + ($ty:ident) => { + impl_vector_element!(trivial, stringify!($ty), stringify!($ty), $ty); + }; +} + +impl_vector_element_for_primitive!(u8); +impl_vector_element_for_primitive!(u16); +impl_vector_element_for_primitive!(u32); +impl_vector_element_for_primitive!(u64); +impl_vector_element_for_primitive!(usize); +impl_vector_element_for_primitive!(i8); +impl_vector_element_for_primitive!(i16); +impl_vector_element_for_primitive!(i32); +impl_vector_element_for_primitive!(i64); +impl_vector_element_for_primitive!(isize); +impl_vector_element_for_primitive!(f32); +impl_vector_element_for_primitive!(f64); + +impl_vector_element!(opaque, "string", "CxxString", CxxString); diff --git a/vendor/cxx/src/exception.rs b/vendor/cxx/src/exception.rs new file mode 100644 index 000000000..259b27d4d --- /dev/null +++ b/vendor/cxx/src/exception.rs @@ -0,0 +1,28 @@ +#![cfg(feature = "alloc")] + +use alloc::boxed::Box; +use core::fmt::{self, Display}; + +/// Exception thrown from an `extern "C++"` function. +#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] +#[derive(Debug)] +pub struct Exception { + pub(crate) what: Box<str>, +} + +impl Display for Exception { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(&self.what) + } +} + +#[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +impl std::error::Error for Exception {} + +impl Exception { + #[allow(missing_docs)] + pub fn what(&self) -> &str { + &self.what + } +} diff --git a/vendor/cxx/src/extern_type.rs b/vendor/cxx/src/extern_type.rs new file mode 100644 index 000000000..d131ae127 --- /dev/null +++ b/vendor/cxx/src/extern_type.rs @@ -0,0 +1,225 @@ +use self::kind::{Kind, Opaque, Trivial}; +use crate::CxxString; +#[cfg(feature = "alloc")] +use alloc::string::String; + +/// A type for which the layout is determined by its C++ definition. +/// +/// This trait serves the following two related purposes. +/// +/// <br> +/// +/// ## Safely unifying occurrences of the same extern type +/// +/// `ExternType` makes it possible for CXX to safely share a consistent Rust +/// type across multiple #\[cxx::bridge\] invocations that refer to a common +/// extern C++ type. +/// +/// In the following snippet, two #\[cxx::bridge\] invocations in different +/// files (possibly different crates) both contain function signatures involving +/// the same C++ type `example::Demo`. If both were written just containing +/// `type Demo;`, then both macro expansions would produce their own separate +/// Rust type called `Demo` and thus the compiler wouldn't allow us to take the +/// `Demo` returned by `file1::ffi::create_demo` and pass it as the `Demo` +/// argument accepted by `file2::ffi::take_ref_demo`. Instead, one of the two +/// `Demo`s has been defined as an extern type alias of the other, making them +/// the same type in Rust. The CXX code generator will use an automatically +/// generated `ExternType` impl emitted in file1 to statically verify that in +/// file2 `crate::file1::ffi::Demo` really does refer to the C++ type +/// `example::Demo` as expected in file2. +/// +/// ```no_run +/// // file1.rs +/// # mod file1 { +/// #[cxx::bridge(namespace = "example")] +/// pub mod ffi { +/// unsafe extern "C++" { +/// type Demo; +/// +/// fn create_demo() -> UniquePtr<Demo>; +/// } +/// } +/// # } +/// +/// // file2.rs +/// #[cxx::bridge(namespace = "example")] +/// pub mod ffi { +/// unsafe extern "C++" { +/// type Demo = crate::file1::ffi::Demo; +/// +/// fn take_ref_demo(demo: &Demo); +/// } +/// } +/// # +/// # fn main() {} +/// ``` +/// +/// <br><br> +/// +/// ## Integrating with bindgen-generated types +/// +/// Handwritten `ExternType` impls make it possible to plug in a data structure +/// emitted by bindgen as the definition of a C++ type emitted by CXX. +/// +/// By writing the unsafe `ExternType` impl, the programmer asserts that the C++ +/// namespace and type name given in the type id refers to a C++ type that is +/// equivalent to Rust type that is the `Self` type of the impl. +/// +/// ```no_run +/// # const _: &str = stringify! { +/// mod folly_sys; // the bindgen-generated bindings +/// # }; +/// # mod folly_sys { +/// # #[repr(transparent)] +/// # pub struct StringPiece([usize; 2]); +/// # } +/// +/// use cxx::{type_id, ExternType}; +/// +/// unsafe impl ExternType for folly_sys::StringPiece { +/// type Id = type_id!("folly::StringPiece"); +/// type Kind = cxx::kind::Opaque; +/// } +/// +/// #[cxx::bridge(namespace = "folly")] +/// pub mod ffi { +/// unsafe extern "C++" { +/// include!("rust_cxx_bindings.h"); +/// +/// type StringPiece = crate::folly_sys::StringPiece; +/// +/// fn print_string_piece(s: &StringPiece); +/// } +/// } +/// +/// // Now if we construct a StringPiece or obtain one through one +/// // of the bindgen-generated signatures, we are able to pass it +/// // along to ffi::print_string_piece. +/// # +/// # fn main() {} +/// ``` +pub unsafe trait ExternType { + /// A type-level representation of the type's C++ namespace and type name. + /// + /// This will always be defined using `type_id!` in the following form: + /// + /// ``` + /// # struct TypeName; + /// # unsafe impl cxx::ExternType for TypeName { + /// type Id = cxx::type_id!("name::space::of::TypeName"); + /// # type Kind = cxx::kind::Opaque; + /// # } + /// ``` + type Id; + + /// Either [`cxx::kind::Opaque`] or [`cxx::kind::Trivial`]. + /// + /// [`cxx::kind::Opaque`]: kind::Opaque + /// [`cxx::kind::Trivial`]: kind::Trivial + /// + /// A C++ type is only okay to hold and pass around by value in Rust if its + /// [move constructor is trivial] and it has no destructor. In CXX, these + /// are called Trivial extern C++ types, while types with nontrivial move + /// behavior or a destructor must be considered Opaque and handled by Rust + /// only behind an indirection, such as a reference or UniquePtr. + /// + /// [move constructor is trivial]: https://en.cppreference.com/w/cpp/types/is_move_constructible + /// + /// If you believe your C++ type reflected by this ExternType impl is indeed + /// fine to hold by value and move in Rust, you can specify: + /// + /// ``` + /// # struct TypeName; + /// # unsafe impl cxx::ExternType for TypeName { + /// # type Id = cxx::type_id!("name::space::of::TypeName"); + /// type Kind = cxx::kind::Trivial; + /// # } + /// ``` + /// + /// which will enable you to pass it into C++ functions by value, return it + /// by value, and include it in `struct`s that you have declared to + /// `cxx::bridge`. Your claim about the triviality of the C++ type will be + /// checked by a `static_assert` in the generated C++ side of the binding. + type Kind: Kind; +} + +/// Marker types identifying Rust's knowledge about an extern C++ type. +/// +/// These markers are used in the [`Kind`][ExternType::Kind] associated type in +/// impls of the `ExternType` trait. Refer to the documentation of `Kind` for an +/// overview of their purpose. +pub mod kind { + use super::private; + + /// An opaque type which cannot be passed or held by value within Rust. + /// + /// Rust's move semantics are such that every move is equivalent to a + /// memcpy. This is incompatible in general with C++'s constructor-based + /// move semantics, so a C++ type which has a destructor or nontrivial move + /// constructor must never exist by value in Rust. In CXX, such types are + /// called opaque C++ types. + /// + /// When passed across an FFI boundary, an opaque C++ type must be behind an + /// indirection such as a reference or UniquePtr. + pub enum Opaque {} + + /// A type with trivial move constructor and no destructor, which can + /// therefore be owned and moved around in Rust code without requiring + /// indirection. + pub enum Trivial {} + + #[allow(missing_docs)] + pub trait Kind: private::Sealed {} + impl Kind for Opaque {} + impl Kind for Trivial {} +} + +mod private { + pub trait Sealed {} + impl Sealed for super::Opaque {} + impl Sealed for super::Trivial {} +} + +#[doc(hidden)] +pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {} + +#[doc(hidden)] +pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {} + +macro_rules! impl_extern_type { + ($([$kind:ident] $($(#[$($attr:tt)*])* $ty:path = $cxxpath:literal)*)*) => { + $($( + $(#[$($attr)*])* + unsafe impl ExternType for $ty { + #[allow(unused_attributes)] // incorrect lint; this doc(hidden) attr *is* respected by rustdoc + #[doc(hidden)] + type Id = crate::type_id!($cxxpath); + type Kind = $kind; + } + )*)* + }; +} + +impl_extern_type! { + [Trivial] + bool = "bool" + u8 = "std::uint8_t" + u16 = "std::uint16_t" + u32 = "std::uint32_t" + u64 = "std::uint64_t" + usize = "size_t" + i8 = "std::int8_t" + i16 = "std::int16_t" + i32 = "std::int32_t" + i64 = "std::int64_t" + isize = "rust::isize" + f32 = "float" + f64 = "double" + + #[cfg(feature = "alloc")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] + String = "rust::String" + + [Opaque] + CxxString = "std::string" +} diff --git a/vendor/cxx/src/fmt.rs b/vendor/cxx/src/fmt.rs new file mode 100644 index 000000000..69614f806 --- /dev/null +++ b/vendor/cxx/src/fmt.rs @@ -0,0 +1,16 @@ +use core::fmt::{self, Display}; + +pub(crate) fn display(fmt: impl Fn(&mut fmt::Formatter) -> fmt::Result) -> impl Display { + DisplayInvoke(fmt) +} + +struct DisplayInvoke<T>(T); + +impl<T> Display for DisplayInvoke<T> +where + T: Fn(&mut fmt::Formatter) -> fmt::Result, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + (self.0)(formatter) + } +} diff --git a/vendor/cxx/src/function.rs b/vendor/cxx/src/function.rs new file mode 100644 index 000000000..f0a201008 --- /dev/null +++ b/vendor/cxx/src/function.rs @@ -0,0 +1,9 @@ +#![allow(missing_docs)] + +use core::ffi::c_void; + +#[repr(C)] +pub struct FatFunction { + pub trampoline: *const c_void, + pub ptr: *const c_void, +} diff --git a/vendor/cxx/src/hash.rs b/vendor/cxx/src/hash.rs new file mode 100644 index 000000000..4c92173f7 --- /dev/null +++ b/vendor/cxx/src/hash.rs @@ -0,0 +1,12 @@ +use core::hash::{Hash, Hasher}; + +#[doc(hidden)] +pub fn hash<V: Hash>(value: &V) -> usize { + #[cfg(feature = "std")] + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + #[cfg(not(feature = "std"))] + let mut hasher = crate::sip::SipHasher13::new(); + + Hash::hash(value, &mut hasher); + Hasher::finish(&hasher) as usize +} diff --git a/vendor/cxx/src/lib.rs b/vendor/cxx/src/lib.rs new file mode 100644 index 000000000..a0b175a7a --- /dev/null +++ b/vendor/cxx/src/lib.rs @@ -0,0 +1,542 @@ +//! [![github]](https://github.com/dtolnay/cxx) [![crates-io]](https://crates.io/crates/cxx) [![docs-rs]](https://docs.rs/cxx) +//! +//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github +//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs +//! +//! <br> +//! +//! This library provides a **safe** mechanism for calling C++ code from Rust +//! and Rust code from C++, not subject to the many ways that things can go +//! wrong when using bindgen or cbindgen to generate unsafe C-style bindings. +//! +//! This doesn't change the fact that 100% of C++ code is unsafe. When auditing +//! a project, you would be on the hook for auditing all the unsafe Rust code +//! and *all* the C++ code. The core safety claim under this new model is that +//! auditing just the C++ side would be sufficient to catch all problems, i.e. +//! the Rust side can be 100% safe. +//! +//! <br> +//! +//! *Compiler support: requires rustc 1.60+ and c++11 or newer*<br> +//! *[Release notes](https://github.com/dtolnay/cxx/releases)* +//! +//! <br> +//! +//! # Guide +//! +//! Please see **<https://cxx.rs>** for a tutorial, reference material, and +//! example code. +//! +//! <br> +//! +//! # Overview +//! +//! The idea is that we define the signatures of both sides of our FFI boundary +//! embedded together in one Rust module (the next section shows an example). +//! From this, CXX receives a complete picture of the boundary to perform static +//! analyses against the types and function signatures to uphold both Rust's and +//! C++'s invariants and requirements. +//! +//! If everything checks out statically, then CXX uses a pair of code generators +//! to emit the relevant `extern "C"` signatures on both sides together with any +//! necessary static assertions for later in the build process to verify +//! correctness. On the Rust side this code generator is simply an attribute +//! procedural macro. On the C++ side it can be a small Cargo build script if +//! your build is managed by Cargo, or for other build systems like Bazel or +//! Buck we provide a command line tool which generates the header and source +//! file and should be easy to integrate. +//! +//! The resulting FFI bridge operates at zero or negligible overhead, i.e. no +//! copying, no serialization, no memory allocation, no runtime checks needed. +//! +//! The FFI signatures are able to use native types from whichever side they +//! please, such as Rust's `String` or C++'s `std::string`, Rust's `Box` or +//! C++'s `std::unique_ptr`, Rust's `Vec` or C++'s `std::vector`, etc in any +//! combination. CXX guarantees an ABI-compatible signature that both sides +//! understand, based on builtin bindings for key standard library types to +//! expose an idiomatic API on those types to the other language. For example +//! when manipulating a C++ string from Rust, its `len()` method becomes a call +//! of the `size()` member function defined by C++; when manipulation a Rust +//! string from C++, its `size()` member function calls Rust's `len()`. +//! +//! <br> +//! +//! # Example +//! +//! In this example we are writing a Rust application that wishes to take +//! advantage of an existing C++ client for a large-file blobstore service. The +//! blobstore supports a `put` operation for a discontiguous buffer upload. For +//! example we might be uploading snapshots of a circular buffer which would +//! tend to consist of 2 chunks, or fragments of a file spread across memory for +//! some other reason. +//! +//! A runnable version of this example is provided under the *demo* directory of +//! <https://github.com/dtolnay/cxx>. To try it out, run `cargo run` from that +//! directory. +//! +//! ```no_run +//! #[cxx::bridge] +//! mod ffi { +//! // Any shared structs, whose fields will be visible to both languages. +//! struct BlobMetadata { +//! size: usize, +//! tags: Vec<String>, +//! } +//! +//! extern "Rust" { +//! // Zero or more opaque types which both languages can pass around but +//! // only Rust can see the fields. +//! type MultiBuf; +//! +//! // Functions implemented in Rust. +//! fn next_chunk(buf: &mut MultiBuf) -> &[u8]; +//! } +//! +//! unsafe extern "C++" { +//! // One or more headers with the matching C++ declarations. Our code +//! // generators don't read it but it gets #include'd and used in static +//! // assertions to ensure our picture of the FFI boundary is accurate. +//! include!("demo/include/blobstore.h"); +//! +//! // Zero or more opaque types which both languages can pass around but +//! // only C++ can see the fields. +//! type BlobstoreClient; +//! +//! // Functions implemented in C++. +//! fn new_blobstore_client() -> UniquePtr<BlobstoreClient>; +//! fn put(&self, parts: &mut MultiBuf) -> u64; +//! fn tag(&self, blobid: u64, tag: &str); +//! fn metadata(&self, blobid: u64) -> BlobMetadata; +//! } +//! } +//! # +//! # pub struct MultiBuf; +//! # +//! # fn next_chunk(_buf: &mut MultiBuf) -> &[u8] { +//! # unimplemented!() +//! # } +//! # +//! # fn main() {} +//! ``` +//! +//! Now we simply provide Rust definitions of all the things in the `extern +//! "Rust"` block and C++ definitions of all the things in the `extern "C++"` +//! block, and get to call back and forth safely. +//! +//! Here are links to the complete set of source files involved in the demo: +//! +//! - [demo/src/main.rs](https://github.com/dtolnay/cxx/blob/master/demo/src/main.rs) +//! - [demo/build.rs](https://github.com/dtolnay/cxx/blob/master/demo/build.rs) +//! - [demo/include/blobstore.h](https://github.com/dtolnay/cxx/blob/master/demo/include/blobstore.h) +//! - [demo/src/blobstore.cc](https://github.com/dtolnay/cxx/blob/master/demo/src/blobstore.cc) +//! +//! To look at the code generated in both languages for the example by the CXX +//! code generators: +//! +//! ```console +//! # run Rust code generator and print to stdout +//! # (requires https://github.com/dtolnay/cargo-expand) +//! $ cargo expand --manifest-path demo/Cargo.toml +//! +//! # run C++ code generator and print to stdout +//! $ cargo run --manifest-path gen/cmd/Cargo.toml -- demo/src/main.rs +//! ``` +//! +//! <br> +//! +//! # Details +//! +//! As seen in the example, the language of the FFI boundary involves 3 kinds of +//! items: +//! +//! - **Shared structs** — their fields are made visible to both +//! languages. The definition written within cxx::bridge is the single source +//! of truth. +//! +//! - **Opaque types** — their fields are secret from the other language. +//! These cannot be passed across the FFI by value but only behind an +//! indirection, such as a reference `&`, a Rust `Box`, or a `UniquePtr`. Can +//! be a type alias for an arbitrarily complicated generic language-specific +//! type depending on your use case. +//! +//! - **Functions** — implemented in either language, callable from the +//! other language. +//! +//! Within the `extern "Rust"` part of the CXX bridge we list the types and +//! functions for which Rust is the source of truth. These all implicitly refer +//! to the `super` module, the parent module of the CXX bridge. You can think of +//! the two items listed in the example above as being like `use +//! super::MultiBuf` and `use super::next_chunk` except re-exported to C++. The +//! parent module will either contain the definitions directly for simple +//! things, or contain the relevant `use` statements to bring them into scope +//! from elsewhere. +//! +//! Within the `extern "C++"` part, we list types and functions for which C++ is +//! the source of truth, as well as the header(s) that declare those APIs. In +//! the future it's possible that this section could be generated bindgen-style +//! from the headers but for now we need the signatures written out; static +//! assertions will verify that they are accurate. +//! +//! Your function implementations themselves, whether in C++ or Rust, *do not* +//! need to be defined as `extern "C"` ABI or no\_mangle. CXX will put in the +//! right shims where necessary to make it all work. +//! +//! <br> +//! +//! # Comparison vs bindgen and cbindgen +//! +//! Notice that with CXX there is repetition of all the function signatures: +//! they are typed out once where the implementation is defined (in C++ or Rust) +//! and again inside the cxx::bridge module, though compile-time assertions +//! guarantee these are kept in sync. This is different from [bindgen] and +//! [cbindgen] where function signatures are typed by a human once and the tool +//! consumes them in one language and emits them in the other language. +//! +//! [bindgen]: https://github.com/rust-lang/rust-bindgen +//! [cbindgen]: https://github.com/eqrion/cbindgen/ +//! +//! This is because CXX fills a somewhat different role. It is a lower level +//! tool than bindgen or cbindgen in a sense; you can think of it as being a +//! replacement for the concept of `extern "C"` signatures as we know them, +//! rather than a replacement for a bindgen. It would be reasonable to build a +//! higher level bindgen-like tool on top of CXX which consumes a C++ header +//! and/or Rust module (and/or IDL like Thrift) as source of truth and generates +//! the cxx::bridge, eliminating the repetition while leveraging the static +//! analysis safety guarantees of CXX. +//! +//! But note in other ways CXX is higher level than the bindgens, with rich +//! support for common standard library types. Frequently with bindgen when we +//! are dealing with an idiomatic C++ API we would end up manually wrapping that +//! API in C-style raw pointer functions, applying bindgen to get unsafe raw +//! pointer Rust functions, and replicating the API again to expose those +//! idiomatically in Rust. That's a much worse form of repetition because it is +//! unsafe all the way through. +//! +//! By using a CXX bridge as the shared understanding between the languages, +//! rather than `extern "C"` C-style signatures as the shared understanding, +//! common FFI use cases become expressible using 100% safe code. +//! +//! It would also be reasonable to mix and match, using CXX bridge for the 95% +//! of your FFI that is straightforward and doing the remaining few oddball +//! signatures the old fashioned way with bindgen and cbindgen, if for some +//! reason CXX's static restrictions get in the way. Please file an issue if you +//! end up taking this approach so that we know what ways it would be worthwhile +//! to make the tool more expressive. +//! +//! <br> +//! +//! # Cargo-based setup +//! +//! For builds that are orchestrated by Cargo, you will use a build script that +//! runs CXX's C++ code generator and compiles the resulting C++ code along with +//! any other C++ code for your crate. +//! +//! The canonical build script is as follows. The indicated line returns a +//! [`cc::Build`] instance (from the usual widely used `cc` crate) on which you +//! can set up any additional source files and compiler flags as normal. +//! +//! [`cc::Build`]: https://docs.rs/cc/1.0/cc/struct.Build.html +//! +//! ```toml +//! # Cargo.toml +//! +//! [build-dependencies] +//! cxx-build = "1.0" +//! ``` +//! +//! ```no_run +//! // build.rs +//! +//! fn main() { +//! cxx_build::bridge("src/main.rs") // returns a cc::Build +//! .file("src/demo.cc") +//! .flag_if_supported("-std=c++11") +//! .compile("cxxbridge-demo"); +//! +//! println!("cargo:rerun-if-changed=src/main.rs"); +//! println!("cargo:rerun-if-changed=src/demo.cc"); +//! println!("cargo:rerun-if-changed=include/demo.h"); +//! } +//! ``` +//! +//! <br><br> +//! +//! # Non-Cargo setup +//! +//! For use in non-Cargo builds like Bazel or Buck, CXX provides an alternate +//! way of invoking the C++ code generator as a standalone command line tool. +//! The tool is packaged as the `cxxbridge-cmd` crate on crates.io or can be +//! built from the *gen/cmd* directory of <https://github.com/dtolnay/cxx>. +//! +//! ```bash +//! $ cargo install cxxbridge-cmd +//! +//! $ cxxbridge src/main.rs --header > path/to/mybridge.h +//! $ cxxbridge src/main.rs > path/to/mybridge.cc +//! ``` +//! +//! <br> +//! +//! # Safety +//! +//! Be aware that the design of this library is intentionally restrictive and +//! opinionated! It isn't a goal to be powerful enough to handle arbitrary +//! signatures in either language. Instead this project is about carving out a +//! reasonably expressive set of functionality about which we can make useful +//! safety guarantees today and maybe extend over time. You may find that it +//! takes some practice to use CXX bridge effectively as it won't work in all +//! the ways that you are used to. +//! +//! Some of the considerations that go into ensuring safety are: +//! +//! - By design, our paired code generators work together to control both sides +//! of the FFI boundary. Ordinarily in Rust writing your own `extern "C"` +//! blocks is unsafe because the Rust compiler has no way to know whether the +//! signatures you've written actually match the signatures implemented in the +//! other language. With CXX we achieve that visibility and know what's on the +//! other side. +//! +//! - Our static analysis detects and prevents passing types by value that +//! shouldn't be passed by value from C++ to Rust, for example because they +//! may contain internal pointers that would be screwed up by Rust's move +//! behavior. +//! +//! - To many people's surprise, it is possible to have a struct in Rust and a +//! struct in C++ with exactly the same layout / fields / alignment / +//! everything, and still not the same ABI when passed by value. This is a +//! longstanding bindgen bug that leads to segfaults in absolutely +//! correct-looking code ([rust-lang/rust-bindgen#778]). CXX knows about this +//! and can insert the necessary zero-cost workaround transparently where +//! needed, so go ahead and pass your structs by value without worries. This +//! is made possible by owning both sides of the boundary rather than just +//! one. +//! +//! - Template instantiations: for example in order to expose a UniquePtr\<T\> +//! type in Rust backed by a real C++ unique\_ptr, we have a way of using a +//! Rust trait to connect the behavior back to the template instantiations +//! performed by the other language. +//! +//! [rust-lang/rust-bindgen#778]: https://github.com/rust-lang/rust-bindgen/issues/778 +//! +//! <br> +//! +//! # Builtin types +//! +//! In addition to all the primitive types (i32 <=> int32_t), the +//! following common types may be used in the fields of shared structs and the +//! arguments and returns of functions. +//! +//! <table> +//! <tr><th>name in Rust</th><th>name in C++</th><th>restrictions</th></tr> +//! <tr><td>String</td><td>rust::String</td><td></td></tr> +//! <tr><td>&str</td><td>rust::Str</td><td></td></tr> +//! <tr><td>&[T]</td><td>rust::Slice<const T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +//! <tr><td>&mut [T]</td><td>rust::Slice<T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +//! <tr><td><a href="struct.CxxString.html">CxxString</a></td><td>std::string</td><td><sup><i>cannot be passed by value</i></sup></td></tr> +//! <tr><td>Box<T></td><td>rust::Box<T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +//! <tr><td><a href="struct.UniquePtr.html">UniquePtr<T></a></td><td>std::unique_ptr<T></td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr> +//! <tr><td><a href="struct.SharedPtr.html">SharedPtr<T></a></td><td>std::shared_ptr<T></td><td><sup><i>cannot hold opaque Rust type</i></sup></td></tr> +//! <tr><td>[T; N]</td><td>std::array<T, N></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +//! <tr><td>Vec<T></td><td>rust::Vec<T></td><td><sup><i>cannot hold opaque C++ type</i></sup></td></tr> +//! <tr><td><a href="struct.CxxVector.html">CxxVector<T></a></td><td>std::vector<T></td><td><sup><i>cannot be passed by value, cannot hold opaque Rust type</i></sup></td></tr> +//! <tr><td>*mut T, *const T</td><td>T*, const T*</td><td><sup><i>fn with a raw pointer argument must be declared unsafe to call</i></sup></td></tr> +//! <tr><td>fn(T, U) -> V</td><td>rust::Fn<V(T, U)></td><td><sup><i>only passing from Rust to C++ is implemented so far</i></sup></td></tr> +//! <tr><td>Result<T></td><td>throw/catch</td><td><sup><i>allowed as return type only</i></sup></td></tr> +//! </table> +//! +//! The C++ API of the `rust` namespace is defined by the *include/cxx.h* file +//! in <https://github.com/dtolnay/cxx>. You will need to include this header in +//! your C++ code when working with those types. +//! +//! The following types are intended to be supported "soon" but are just not +//! implemented yet. I don't expect any of these to be hard to make work but +//! it's a matter of designing a nice API for each in its non-native language. +//! +//! <table> +//! <tr><th>name in Rust</th><th>name in C++</th></tr> +//! <tr><td>BTreeMap<K, V></td><td><sup><i>tbd</i></sup></td></tr> +//! <tr><td>HashMap<K, V></td><td><sup><i>tbd</i></sup></td></tr> +//! <tr><td>Arc<T></td><td><sup><i>tbd</i></sup></td></tr> +//! <tr><td>Option<T></td><td><sup><i>tbd</i></sup></td></tr> +//! <tr><td><sup><i>tbd</i></sup></td><td>std::map<K, V></td></tr> +//! <tr><td><sup><i>tbd</i></sup></td><td>std::unordered_map<K, V></td></tr> +//! </table> + +#![no_std] +#![doc(html_root_url = "https://docs.rs/cxx/1.0.94")] +#![deny( + improper_ctypes, + improper_ctypes_definitions, + missing_docs, + unsafe_op_in_unsafe_fn +)] +#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![allow(non_camel_case_types)] +#![allow( + clippy::cognitive_complexity, + clippy::declare_interior_mutable_const, + clippy::doc_markdown, + clippy::empty_enum, + clippy::extra_unused_type_parameters, + clippy::inherent_to_string, + clippy::items_after_statements, + clippy::large_enum_variant, + clippy::len_without_is_empty, + clippy::missing_errors_doc, + clippy::missing_safety_doc, + clippy::module_inception, + clippy::module_name_repetitions, + clippy::must_use_candidate, + clippy::needless_doctest_main, + clippy::new_without_default, + clippy::or_fun_call, + clippy::ptr_arg, + clippy::toplevel_ref_arg, + clippy::transmute_undefined_repr, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/8417 + clippy::useless_let_if_seq, + clippy::wrong_self_convention +)] + +#[cfg(built_with_cargo)] +extern crate link_cplusplus; + +extern crate self as cxx; + +#[doc(hidden)] +pub extern crate core; + +#[cfg(feature = "alloc")] +#[doc(hidden)] +pub extern crate alloc; + +#[cfg(not(feature = "alloc"))] +extern crate core as alloc; + +#[cfg(feature = "std")] +#[doc(hidden)] +pub extern crate std; + +// Block inadvertent use of items from libstd, which does not otherwise produce +// a compile-time error on edition 2018+. +#[cfg(not(feature = "std"))] +extern crate core as std; + +#[cfg(not(any(feature = "alloc", cxx_experimental_no_alloc)))] +compile_error! { + r#"cxx support for no_alloc is incomplete and semver exempt; you must build with at least one of feature="std", feature="alloc", or RUSTFLAGS='--cfg cxx_experimental_no_alloc'"# +} + +#[cfg(all(compile_error_if_alloc, feature = "alloc"))] +compile_error! { + r#"feature="alloc" is unexpectedly enabled"# +} + +#[cfg(all(compile_error_if_std, feature = "std"))] +compile_error! { + r#"feature="std" is unexpectedly enabled"# +} + +#[macro_use] +mod macros; + +mod c_char; +mod cxx_vector; +mod exception; +mod extern_type; +mod fmt; +mod function; +mod hash; +mod lossy; +pub mod memory; +mod opaque; +mod result; +mod rust_slice; +mod rust_str; +mod rust_string; +mod rust_type; +mod rust_vec; +mod shared_ptr; +mod sip; +#[path = "cxx_string.rs"] +mod string; +mod symbols; +mod type_id; +mod unique_ptr; +mod unwind; +pub mod vector; +mod weak_ptr; + +pub use crate::cxx_vector::CxxVector; +#[cfg(feature = "alloc")] +pub use crate::exception::Exception; +pub use crate::extern_type::{kind, ExternType}; +pub use crate::shared_ptr::SharedPtr; +pub use crate::string::CxxString; +pub use crate::unique_ptr::UniquePtr; +pub use crate::weak_ptr::WeakPtr; +pub use cxxbridge_macro::bridge; + +/// Synonym for `CxxString`. +/// +/// To avoid confusion with Rust's standard library string you probably +/// shouldn't import this type with `use`. Instead, write `cxx::String`, or +/// import and use `CxxString`. +pub type String = CxxString; + +/// Synonym for `CxxVector`. +/// +/// To avoid confusion with Rust's standard library vector you probably +/// shouldn't import this type with `use`. Instead, write `cxx::Vector<T>`, or +/// import and use `CxxVector`. +pub type Vector<T> = CxxVector<T>; + +// Not public API. +#[doc(hidden)] +pub mod private { + pub use crate::c_char::c_char; + pub use crate::cxx_vector::VectorElement; + pub use crate::extern_type::{verify_extern_kind, verify_extern_type}; + pub use crate::function::FatFunction; + pub use crate::hash::hash; + pub use crate::opaque::Opaque; + #[cfg(feature = "alloc")] + pub use crate::result::{r#try, Result}; + pub use crate::rust_slice::RustSlice; + pub use crate::rust_str::RustStr; + #[cfg(feature = "alloc")] + pub use crate::rust_string::RustString; + pub use crate::rust_type::{ImplBox, ImplVec, RustType}; + #[cfg(feature = "alloc")] + pub use crate::rust_vec::RustVec; + pub use crate::shared_ptr::SharedPtrTarget; + pub use crate::string::StackString; + pub use crate::unique_ptr::UniquePtrTarget; + pub use crate::unwind::prevent_unwind; + pub use crate::weak_ptr::WeakPtrTarget; + pub use core::{concat, module_path}; + pub use cxxbridge_macro::type_id; +} + +mod actually_private { + pub trait Private {} +} + +macro_rules! chars { + ($($ch:ident)*) => { + $( + #[doc(hidden)] + pub enum $ch {} + )* + }; +} + +chars! { + _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 + A B C D E F G H I J K L M N O P Q R S T U V W X Y Z + a b c d e f g h i j k l m n o p q r s t u v w x y z + __ // underscore +} + +#[repr(transparent)] +struct void(core::ffi::c_void); diff --git a/vendor/cxx/src/lossy.rs b/vendor/cxx/src/lossy.rs new file mode 100644 index 000000000..8ccf0f93b --- /dev/null +++ b/vendor/cxx/src/lossy.rs @@ -0,0 +1,67 @@ +use core::char; +use core::fmt::{self, Write as _}; +use core::str; + +pub fn display(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result { + loop { + match str::from_utf8(bytes) { + Ok(valid) => return f.write_str(valid), + Err(utf8_error) => { + let valid_up_to = utf8_error.valid_up_to(); + let valid = unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) }; + f.write_str(valid)?; + f.write_char(char::REPLACEMENT_CHARACTER)?; + if let Some(error_len) = utf8_error.error_len() { + bytes = &bytes[valid_up_to + error_len..]; + } else { + return Ok(()); + } + } + } + } +} + +pub fn debug(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result { + f.write_char('"')?; + + while !bytes.is_empty() { + let from_utf8_result = str::from_utf8(bytes); + let valid = match from_utf8_result { + Ok(valid) => valid, + Err(utf8_error) => { + let valid_up_to = utf8_error.valid_up_to(); + unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) } + } + }; + + let mut written = 0; + for (i, ch) in valid.char_indices() { + let esc = ch.escape_debug(); + if esc.len() != 1 && ch != '\'' { + f.write_str(&valid[written..i])?; + for ch in esc { + f.write_char(ch)?; + } + written = i + ch.len_utf8(); + } + } + f.write_str(&valid[written..])?; + + match from_utf8_result { + Ok(_valid) => break, + Err(utf8_error) => { + let end_of_broken = if let Some(error_len) = utf8_error.error_len() { + valid.len() + error_len + } else { + bytes.len() + }; + for b in &bytes[valid.len()..end_of_broken] { + write!(f, "\\x{:02x}", b)?; + } + bytes = &bytes[end_of_broken..]; + } + } + } + + f.write_char('"') +} diff --git a/vendor/cxx/src/macros/assert.rs b/vendor/cxx/src/macros/assert.rs new file mode 100644 index 000000000..5d5ea9e35 --- /dev/null +++ b/vendor/cxx/src/macros/assert.rs @@ -0,0 +1,7 @@ +#[macro_export] +#[doc(hidden)] +macro_rules! const_assert_eq { + ($left:expr, $right:expr $(,)?) => { + const _: [(); $left] = [(); $right]; + }; +} diff --git a/vendor/cxx/src/macros/concat.rs b/vendor/cxx/src/macros/concat.rs new file mode 100644 index 000000000..5ee77c527 --- /dev/null +++ b/vendor/cxx/src/macros/concat.rs @@ -0,0 +1,8 @@ +#[macro_export] +#[doc(hidden)] +macro_rules! attr { + (#[$name:ident = $value:expr] $($rest:tt)*) => { + #[$name = $value] + $($rest)* + }; +} diff --git a/vendor/cxx/src/macros/mod.rs b/vendor/cxx/src/macros/mod.rs new file mode 100644 index 000000000..d12d96bd4 --- /dev/null +++ b/vendor/cxx/src/macros/mod.rs @@ -0,0 +1,4 @@ +#[macro_use] +mod assert; +#[macro_use] +mod concat; diff --git a/vendor/cxx/src/memory.rs b/vendor/cxx/src/memory.rs new file mode 100644 index 000000000..fd8df12a8 --- /dev/null +++ b/vendor/cxx/src/memory.rs @@ -0,0 +1,9 @@ +//! Less used details of `UniquePtr` and `SharedPtr`. +//! +//! The pointer types themselves are exposed at the crate root. + +pub use crate::shared_ptr::SharedPtrTarget; +pub use crate::unique_ptr::UniquePtrTarget; +pub use crate::weak_ptr::WeakPtrTarget; +#[doc(no_inline)] +pub use cxx::{SharedPtr, UniquePtr}; diff --git a/vendor/cxx/src/opaque.rs b/vendor/cxx/src/opaque.rs new file mode 100644 index 000000000..e0f8ce2c2 --- /dev/null +++ b/vendor/cxx/src/opaque.rs @@ -0,0 +1,20 @@ +#![allow(missing_docs)] + +use crate::void; +use core::marker::{PhantomData, PhantomPinned}; +use core::mem; + +// . size = 0 +// . align = 1 +// . ffi-safe +// . !Send +// . !Sync +// . !Unpin +#[repr(C, packed)] +pub struct Opaque { + _private: [*const void; 0], + _pinned: PhantomData<PhantomPinned>, +} + +const_assert_eq!(0, mem::size_of::<Opaque>()); +const_assert_eq!(1, mem::align_of::<Opaque>()); diff --git a/vendor/cxx/src/result.rs b/vendor/cxx/src/result.rs new file mode 100644 index 000000000..ba77858e3 --- /dev/null +++ b/vendor/cxx/src/result.rs @@ -0,0 +1,70 @@ +#![cfg(feature = "alloc")] +#![allow(missing_docs)] + +use crate::exception::Exception; +use alloc::boxed::Box; +use alloc::string::{String, ToString}; +use core::fmt::Display; +use core::ptr::{self, NonNull}; +use core::result::Result as StdResult; +use core::slice; +use core::str; + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct PtrLen { + pub ptr: NonNull<u8>, + pub len: usize, +} + +#[repr(C)] +pub union Result { + err: PtrLen, + ok: *const u8, // null +} + +pub unsafe fn r#try<T, E>(ret: *mut T, result: StdResult<T, E>) -> Result +where + E: Display, +{ + match result { + Ok(ok) => { + unsafe { ptr::write(ret, ok) } + Result { ok: ptr::null() } + } + Err(err) => unsafe { to_c_error(err.to_string()) }, + } +} + +unsafe fn to_c_error(msg: String) -> Result { + let mut msg = msg; + unsafe { msg.as_mut_vec() }.push(b'\0'); + let ptr = msg.as_ptr(); + let len = msg.len(); + + extern "C" { + #[link_name = "cxxbridge1$error"] + fn error(ptr: *const u8, len: usize) -> NonNull<u8>; + } + + let copy = unsafe { error(ptr, len) }; + let err = PtrLen { ptr: copy, len }; + Result { err } +} + +impl Result { + pub unsafe fn exception(self) -> StdResult<(), Exception> { + unsafe { + if self.ok.is_null() { + Ok(()) + } else { + let err = self.err; + let slice = slice::from_raw_parts_mut(err.ptr.as_ptr(), err.len); + let s = str::from_utf8_unchecked_mut(slice); + Err(Exception { + what: Box::from_raw(s), + }) + } + } + } +} diff --git a/vendor/cxx/src/rust_slice.rs b/vendor/cxx/src/rust_slice.rs new file mode 100644 index 000000000..069631176 --- /dev/null +++ b/vendor/cxx/src/rust_slice.rs @@ -0,0 +1,66 @@ +#![allow(missing_docs)] + +use core::mem::{self, MaybeUninit}; +use core::ptr::{self, NonNull}; +use core::slice; + +// ABI compatible with C++ rust::Slice<T> (not necessarily &[T]). +#[repr(C)] +pub struct RustSlice { + repr: [MaybeUninit<usize>; mem::size_of::<NonNull<[()]>>() / mem::size_of::<usize>()], +} + +impl RustSlice { + pub fn from_ref<T>(slice: &[T]) -> Self { + let ptr = NonNull::from(slice).cast::<T>(); + let len = slice.len(); + Self::from_raw_parts(ptr, len) + } + + pub fn from_mut<T>(slice: &mut [T]) -> Self { + let ptr = NonNull::from(&mut *slice).cast::<T>(); + let len = slice.len(); + Self::from_raw_parts(ptr, len) + } + + pub unsafe fn as_slice<'a, T>(self) -> &'a [T] { + let ptr = self.as_non_null_ptr().as_ptr(); + let len = self.len(); + unsafe { slice::from_raw_parts(ptr, len) } + } + + pub unsafe fn as_mut_slice<'a, T>(self) -> &'a mut [T] { + let ptr = self.as_non_null_ptr().as_ptr(); + let len = self.len(); + unsafe { slice::from_raw_parts_mut(ptr, len) } + } + + pub(crate) fn from_raw_parts<T>(ptr: NonNull<T>, len: usize) -> Self { + // TODO: use NonNull::from_raw_parts(ptr.cast(), len) when stable. + // https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.from_raw_parts + // https://github.com/rust-lang/rust/issues/81513 + let ptr = ptr::slice_from_raw_parts_mut(ptr.as_ptr().cast(), len); + unsafe { mem::transmute::<NonNull<[()]>, RustSlice>(NonNull::new_unchecked(ptr)) } + } + + pub(crate) fn as_non_null_ptr<T>(&self) -> NonNull<T> { + let rust_slice = RustSlice { repr: self.repr }; + let repr = unsafe { mem::transmute::<RustSlice, NonNull<[()]>>(rust_slice) }; + repr.cast() + } + + pub(crate) fn len(&self) -> usize { + let rust_slice = RustSlice { repr: self.repr }; + let repr = unsafe { mem::transmute::<RustSlice, NonNull<[()]>>(rust_slice) }; + // TODO: use repr.len() when stable. + // https://doc.rust-lang.org/nightly/std/ptr/struct.NonNull.html#method.len + // https://github.com/rust-lang/rust/issues/71146 + unsafe { repr.as_ref() }.len() + } +} + +const_assert_eq!(mem::size_of::<NonNull<[()]>>(), mem::size_of::<RustSlice>()); +const_assert_eq!( + mem::align_of::<NonNull<[()]>>(), + mem::align_of::<RustSlice>(), +); diff --git a/vendor/cxx/src/rust_str.rs b/vendor/cxx/src/rust_str.rs new file mode 100644 index 000000000..b1b46e3e9 --- /dev/null +++ b/vendor/cxx/src/rust_str.rs @@ -0,0 +1,28 @@ +#![allow(missing_docs)] + +use core::mem::{self, MaybeUninit}; +use core::ptr::NonNull; +use core::str; + +// ABI compatible with C++ rust::Str (not necessarily &str). +#[repr(C)] +pub struct RustStr { + repr: [MaybeUninit<usize>; mem::size_of::<NonNull<str>>() / mem::size_of::<usize>()], +} + +impl RustStr { + pub fn from(repr: &str) -> Self { + let repr = NonNull::from(repr); + unsafe { mem::transmute::<NonNull<str>, RustStr>(repr) } + } + + pub unsafe fn as_str<'a>(self) -> &'a str { + unsafe { + let repr = mem::transmute::<RustStr, NonNull<str>>(self); + &*repr.as_ptr() + } + } +} + +const_assert_eq!(mem::size_of::<NonNull<str>>(), mem::size_of::<RustStr>()); +const_assert_eq!(mem::align_of::<NonNull<str>>(), mem::align_of::<RustStr>()); diff --git a/vendor/cxx/src/rust_string.rs b/vendor/cxx/src/rust_string.rs new file mode 100644 index 000000000..0e0c5a836 --- /dev/null +++ b/vendor/cxx/src/rust_string.rs @@ -0,0 +1,48 @@ +#![cfg(feature = "alloc")] +#![allow(missing_docs)] + +use alloc::string::String; +use core::mem::{self, MaybeUninit}; +use core::ptr; + +// ABI compatible with C++ rust::String (not necessarily alloc::string::String). +#[repr(C)] +pub struct RustString { + repr: [MaybeUninit<usize>; mem::size_of::<String>() / mem::size_of::<usize>()], +} + +impl RustString { + pub fn from(s: String) -> Self { + unsafe { mem::transmute::<String, RustString>(s) } + } + + pub fn from_ref(s: &String) -> &Self { + unsafe { &*(s as *const String as *const RustString) } + } + + pub fn from_mut(s: &mut String) -> &mut Self { + unsafe { &mut *(s as *mut String as *mut RustString) } + } + + pub fn into_string(self) -> String { + unsafe { mem::transmute::<RustString, String>(self) } + } + + pub fn as_string(&self) -> &String { + unsafe { &*(self as *const RustString as *const String) } + } + + pub fn as_mut_string(&mut self) -> &mut String { + unsafe { &mut *(self as *mut RustString as *mut String) } + } +} + +impl Drop for RustString { + fn drop(&mut self) { + unsafe { ptr::drop_in_place(self.as_mut_string()) } + } +} + +const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<RustString>()); +const_assert_eq!(mem::size_of::<String>(), mem::size_of::<RustString>()); +const_assert_eq!(mem::align_of::<String>(), mem::align_of::<RustString>()); diff --git a/vendor/cxx/src/rust_type.rs b/vendor/cxx/src/rust_type.rs new file mode 100644 index 000000000..eacb5309f --- /dev/null +++ b/vendor/cxx/src/rust_type.rs @@ -0,0 +1,5 @@ +#![allow(missing_docs)] + +pub unsafe trait RustType {} +pub unsafe trait ImplBox {} +pub unsafe trait ImplVec {} diff --git a/vendor/cxx/src/rust_vec.rs b/vendor/cxx/src/rust_vec.rs new file mode 100644 index 000000000..acb7e8902 --- /dev/null +++ b/vendor/cxx/src/rust_vec.rs @@ -0,0 +1,115 @@ +#![cfg(feature = "alloc")] +#![allow(missing_docs)] + +use crate::rust_string::RustString; +use alloc::string::String; +use alloc::vec::Vec; +use core::ffi::c_void; +use core::marker::PhantomData; +use core::mem::{self, ManuallyDrop, MaybeUninit}; +use core::ptr; + +// ABI compatible with C++ rust::Vec<T> (not necessarily alloc::vec::Vec<T>). +#[repr(C)] +pub struct RustVec<T> { + repr: [MaybeUninit<usize>; mem::size_of::<Vec<c_void>>() / mem::size_of::<usize>()], + marker: PhantomData<Vec<T>>, +} + +impl<T> RustVec<T> { + pub fn new() -> Self { + Self::from(Vec::new()) + } + + pub fn from(v: Vec<T>) -> Self { + unsafe { mem::transmute::<Vec<T>, RustVec<T>>(v) } + } + + pub fn from_ref(v: &Vec<T>) -> &Self { + unsafe { &*(v as *const Vec<T> as *const RustVec<T>) } + } + + pub fn from_mut(v: &mut Vec<T>) -> &mut Self { + unsafe { &mut *(v as *mut Vec<T> as *mut RustVec<T>) } + } + + pub fn into_vec(self) -> Vec<T> { + unsafe { mem::transmute::<RustVec<T>, Vec<T>>(self) } + } + + pub fn as_vec(&self) -> &Vec<T> { + unsafe { &*(self as *const RustVec<T> as *const Vec<T>) } + } + + pub fn as_mut_vec(&mut self) -> &mut Vec<T> { + unsafe { &mut *(self as *mut RustVec<T> as *mut Vec<T>) } + } + + pub fn len(&self) -> usize { + self.as_vec().len() + } + + pub fn capacity(&self) -> usize { + self.as_vec().capacity() + } + + pub fn as_ptr(&self) -> *const T { + self.as_vec().as_ptr() + } + + pub fn reserve_total(&mut self, new_cap: usize) { + let vec = self.as_mut_vec(); + if new_cap > vec.capacity() { + let additional = new_cap - vec.len(); + vec.reserve(additional); + } + } + + pub unsafe fn set_len(&mut self, len: usize) { + unsafe { self.as_mut_vec().set_len(len) } + } + + pub fn truncate(&mut self, len: usize) { + self.as_mut_vec().truncate(len); + } +} + +impl RustVec<RustString> { + pub fn from_vec_string(v: Vec<String>) -> Self { + let mut v = ManuallyDrop::new(v); + let ptr = v.as_mut_ptr().cast::<RustString>(); + let len = v.len(); + let cap = v.capacity(); + Self::from(unsafe { Vec::from_raw_parts(ptr, len, cap) }) + } + + pub fn from_ref_vec_string(v: &Vec<String>) -> &Self { + Self::from_ref(unsafe { &*(v as *const Vec<String> as *const Vec<RustString>) }) + } + + pub fn from_mut_vec_string(v: &mut Vec<String>) -> &mut Self { + Self::from_mut(unsafe { &mut *(v as *mut Vec<String> as *mut Vec<RustString>) }) + } + + pub fn into_vec_string(self) -> Vec<String> { + let mut v = ManuallyDrop::new(self.into_vec()); + let ptr = v.as_mut_ptr().cast::<String>(); + let len = v.len(); + let cap = v.capacity(); + unsafe { Vec::from_raw_parts(ptr, len, cap) } + } + + pub fn as_vec_string(&self) -> &Vec<String> { + unsafe { &*(self as *const RustVec<RustString> as *const Vec<String>) } + } + + pub fn as_mut_vec_string(&mut self) -> &mut Vec<String> { + unsafe { &mut *(self as *mut RustVec<RustString> as *mut Vec<String>) } + } +} + +impl<T> Drop for RustVec<T> { + fn drop(&mut self) { + unsafe { ptr::drop_in_place(self.as_mut_vec()) } + } +} diff --git a/vendor/cxx/src/shared_ptr.rs b/vendor/cxx/src/shared_ptr.rs new file mode 100644 index 000000000..64c866196 --- /dev/null +++ b/vendor/cxx/src/shared_ptr.rs @@ -0,0 +1,283 @@ +use crate::fmt::display; +use crate::kind::Trivial; +use crate::string::CxxString; +use crate::weak_ptr::{WeakPtr, WeakPtrTarget}; +use crate::ExternType; +use core::ffi::c_void; +use core::fmt::{self, Debug, Display}; +use core::marker::PhantomData; +use core::mem::MaybeUninit; +use core::ops::Deref; + +/// Binding to C++ `std::shared_ptr<T>`. +#[repr(C)] +pub struct SharedPtr<T> +where + T: SharedPtrTarget, +{ + repr: [MaybeUninit<*mut c_void>; 2], + ty: PhantomData<T>, +} + +impl<T> SharedPtr<T> +where + T: SharedPtrTarget, +{ + /// Makes a new SharedPtr wrapping a null pointer. + /// + /// Matches the behavior of default-constructing a std::shared\_ptr. + pub fn null() -> Self { + let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit(); + let new = shared_ptr.as_mut_ptr().cast(); + unsafe { + T::__null(new); + shared_ptr.assume_init() + } + } + + /// Allocates memory on the heap and makes a SharedPtr owner for it. + pub fn new(value: T) -> Self + where + T: ExternType<Kind = Trivial>, + { + let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit(); + let new = shared_ptr.as_mut_ptr().cast(); + unsafe { + T::__new(value, new); + shared_ptr.assume_init() + } + } + + /// Checks whether the SharedPtr does not own an object. + /// + /// This is the opposite of [std::shared_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/shared_ptr/operator_bool). + pub fn is_null(&self) -> bool { + let this = self as *const Self as *const c_void; + let ptr = unsafe { T::__get(this) }; + ptr.is_null() + } + + /// Returns a reference to the object owned by this SharedPtr if any, + /// otherwise None. + pub fn as_ref(&self) -> Option<&T> { + let this = self as *const Self as *const c_void; + unsafe { T::__get(this).as_ref() } + } + + /// Constructs new WeakPtr as a non-owning reference to the object managed + /// by `self`. If `self` manages no object, the WeakPtr manages no object + /// too. + /// + /// Matches the behavior of [std::weak_ptr\<T\>::weak_ptr(const std::shared_ptr\<T\> \&)](https://en.cppreference.com/w/cpp/memory/weak_ptr/weak_ptr). + pub fn downgrade(self: &SharedPtr<T>) -> WeakPtr<T> + where + T: WeakPtrTarget, + { + let this = self as *const Self as *const c_void; + let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit(); + let new = weak_ptr.as_mut_ptr().cast(); + unsafe { + T::__downgrade(this, new); + weak_ptr.assume_init() + } + } +} + +unsafe impl<T> Send for SharedPtr<T> where T: Send + Sync + SharedPtrTarget {} +unsafe impl<T> Sync for SharedPtr<T> where T: Send + Sync + SharedPtrTarget {} + +impl<T> Clone for SharedPtr<T> +where + T: SharedPtrTarget, +{ + fn clone(&self) -> Self { + let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit(); + let new = shared_ptr.as_mut_ptr().cast(); + let this = self as *const Self as *mut c_void; + unsafe { + T::__clone(this, new); + shared_ptr.assume_init() + } + } +} + +// SharedPtr is not a self-referential type and is safe to move out of a Pin, +// regardless whether the pointer's target is Unpin. +impl<T> Unpin for SharedPtr<T> where T: SharedPtrTarget {} + +impl<T> Drop for SharedPtr<T> +where + T: SharedPtrTarget, +{ + fn drop(&mut self) { + let this = self as *mut Self as *mut c_void; + unsafe { T::__drop(this) } + } +} + +impl<T> Deref for SharedPtr<T> +where + T: SharedPtrTarget, +{ + type Target = T; + + fn deref(&self) -> &Self::Target { + match self.as_ref() { + Some(target) => target, + None => panic!( + "called deref on a null SharedPtr<{}>", + display(T::__typename), + ), + } + } +} + +impl<T> Debug for SharedPtr<T> +where + T: Debug + SharedPtrTarget, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self.as_ref() { + None => formatter.write_str("nullptr"), + Some(value) => Debug::fmt(value, formatter), + } + } +} + +impl<T> Display for SharedPtr<T> +where + T: Display + SharedPtrTarget, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self.as_ref() { + None => formatter.write_str("nullptr"), + Some(value) => Display::fmt(value, formatter), + } + } +} + +/// Trait bound for types which may be used as the `T` inside of a +/// `SharedPtr<T>` in generic code. +/// +/// This trait has no publicly callable or implementable methods. Implementing +/// it outside of the CXX codebase is not supported. +/// +/// # Example +/// +/// A bound `T: SharedPtrTarget` may be necessary when manipulating +/// [`SharedPtr`] in generic code. +/// +/// ``` +/// use cxx::memory::{SharedPtr, SharedPtrTarget}; +/// use std::fmt::Display; +/// +/// pub fn take_generic_ptr<T>(ptr: SharedPtr<T>) +/// where +/// T: SharedPtrTarget + Display, +/// { +/// println!("the shared_ptr points to: {}", *ptr); +/// } +/// ``` +/// +/// Writing the same generic function without a `SharedPtrTarget` trait bound +/// would not compile. +pub unsafe trait SharedPtrTarget { + #[doc(hidden)] + fn __typename(f: &mut fmt::Formatter) -> fmt::Result; + #[doc(hidden)] + unsafe fn __null(new: *mut c_void); + #[doc(hidden)] + unsafe fn __new(value: Self, new: *mut c_void) + where + Self: Sized, + { + // Opoaque C types do not get this method because they can never exist + // by value on the Rust side of the bridge. + let _ = value; + let _ = new; + unreachable!() + } + #[doc(hidden)] + unsafe fn __clone(this: *const c_void, new: *mut c_void); + #[doc(hidden)] + unsafe fn __get(this: *const c_void) -> *const Self; + #[doc(hidden)] + unsafe fn __drop(this: *mut c_void); +} + +macro_rules! impl_shared_ptr_target { + ($segment:expr, $name:expr, $ty:ty) => { + unsafe impl SharedPtrTarget for $ty { + fn __typename(f: &mut fmt::Formatter) -> fmt::Result { + f.write_str($name) + } + unsafe fn __null(new: *mut c_void) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$null")] + fn __null(new: *mut c_void); + } + } + unsafe { __null(new) } + } + unsafe fn __new(value: Self, new: *mut c_void) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$uninit")] + fn __uninit(new: *mut c_void) -> *mut c_void; + } + } + unsafe { __uninit(new).cast::<$ty>().write(value) } + } + unsafe fn __clone(this: *const c_void, new: *mut c_void) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$clone")] + fn __clone(this: *const c_void, new: *mut c_void); + } + } + unsafe { __clone(this, new) } + } + unsafe fn __get(this: *const c_void) -> *const Self { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$get")] + fn __get(this: *const c_void) -> *const c_void; + } + } + unsafe { __get(this) }.cast() + } + unsafe fn __drop(this: *mut c_void) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$shared_ptr$", $segment, "$drop")] + fn __drop(this: *mut c_void); + } + } + unsafe { __drop(this) } + } + } + }; +} + +macro_rules! impl_shared_ptr_target_for_primitive { + ($ty:ident) => { + impl_shared_ptr_target!(stringify!($ty), stringify!($ty), $ty); + }; +} + +impl_shared_ptr_target_for_primitive!(bool); +impl_shared_ptr_target_for_primitive!(u8); +impl_shared_ptr_target_for_primitive!(u16); +impl_shared_ptr_target_for_primitive!(u32); +impl_shared_ptr_target_for_primitive!(u64); +impl_shared_ptr_target_for_primitive!(usize); +impl_shared_ptr_target_for_primitive!(i8); +impl_shared_ptr_target_for_primitive!(i16); +impl_shared_ptr_target_for_primitive!(i32); +impl_shared_ptr_target_for_primitive!(i64); +impl_shared_ptr_target_for_primitive!(isize); +impl_shared_ptr_target_for_primitive!(f32); +impl_shared_ptr_target_for_primitive!(f64); + +impl_shared_ptr_target!("string", "CxxString", CxxString); diff --git a/vendor/cxx/src/sip.rs b/vendor/cxx/src/sip.rs new file mode 100644 index 000000000..9e1d050a5 --- /dev/null +++ b/vendor/cxx/src/sip.rs @@ -0,0 +1,228 @@ +// Vendored from libstd: +// https://github.com/rust-lang/rust/blob/1.57.0/library/core/src/hash/sip.rs +// +// TODO: maybe depend on a hasher from crates.io if this becomes annoying to +// maintain, or change this to a simpler one. + +#![cfg(not(feature = "std"))] + +use core::cmp; +use core::hash::Hasher; +use core::mem; +use core::ptr; + +/// An implementation of SipHash 1-3. +/// +/// This is currently the default hashing function used by standard library +/// (e.g., `collections::HashMap` uses it by default). +/// +/// See: <https://131002.net/siphash> +pub struct SipHasher13 { + k0: u64, + k1: u64, + length: usize, // how many bytes we've processed + state: State, // hash State + tail: u64, // unprocessed bytes le + ntail: usize, // how many bytes in tail are valid +} + +#[derive(Clone, Copy)] +#[repr(C)] +struct State { + // v0, v2 and v1, v3 show up in pairs in the algorithm, + // and simd implementations of SipHash will use vectors + // of v02 and v13. By placing them in this order in the struct, + // the compiler can pick up on just a few simd optimizations by itself. + v0: u64, + v2: u64, + v1: u64, + v3: u64, +} + +macro_rules! compress { + ($state:expr) => { + compress!($state.v0, $state.v1, $state.v2, $state.v3) + }; + ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => { + $v0 = $v0.wrapping_add($v1); + $v1 = $v1.rotate_left(13); + $v1 ^= $v0; + $v0 = $v0.rotate_left(32); + $v2 = $v2.wrapping_add($v3); + $v3 = $v3.rotate_left(16); + $v3 ^= $v2; + $v0 = $v0.wrapping_add($v3); + $v3 = $v3.rotate_left(21); + $v3 ^= $v0; + $v2 = $v2.wrapping_add($v1); + $v1 = $v1.rotate_left(17); + $v1 ^= $v2; + $v2 = $v2.rotate_left(32); + }; +} + +/// Loads an integer of the desired type from a byte stream, in LE order. Uses +/// `copy_nonoverlapping` to let the compiler generate the most efficient way +/// to load it from a possibly unaligned address. +/// +/// Unsafe because: unchecked indexing at i..i+size_of(int_ty) +macro_rules! load_int_le { + ($buf:expr, $i:expr, $int_ty:ident) => {{ + debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len()); + let mut data = 0 as $int_ty; + ptr::copy_nonoverlapping( + $buf.as_ptr().add($i), + &mut data as *mut _ as *mut u8, + mem::size_of::<$int_ty>(), + ); + data.to_le() + }}; +} + +/// Loads a u64 using up to 7 bytes of a byte slice. It looks clumsy but the +/// `copy_nonoverlapping` calls that occur (via `load_int_le!`) all have fixed +/// sizes and avoid calling `memcpy`, which is good for speed. +/// +/// Unsafe because: unchecked indexing at start..start+len +unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { + debug_assert!(len < 8); + let mut i = 0; // current byte index (from LSB) in the output u64 + let mut out = 0; + if i + 3 < len { + // SAFETY: `i` cannot be greater than `len`, and the caller must guarantee + // that the index start..start+len is in bounds. + out = unsafe { load_int_le!(buf, start + i, u32) } as u64; + i += 4; + } + if i + 1 < len { + // SAFETY: same as above. + out |= (unsafe { load_int_le!(buf, start + i, u16) } as u64) << (i * 8); + i += 2 + } + if i < len { + // SAFETY: same as above. + out |= (unsafe { *buf.get_unchecked(start + i) } as u64) << (i * 8); + i += 1; + } + debug_assert_eq!(i, len); + out +} + +impl SipHasher13 { + /// Creates a new `SipHasher13` with the two initial keys set to 0. + pub fn new() -> Self { + Self::new_with_keys(0, 0) + } + + /// Creates a `SipHasher13` that is keyed off the provided keys. + fn new_with_keys(key0: u64, key1: u64) -> Self { + let mut state = SipHasher13 { + k0: key0, + k1: key1, + length: 0, + state: State { + v0: 0, + v1: 0, + v2: 0, + v3: 0, + }, + tail: 0, + ntail: 0, + }; + state.reset(); + state + } + + fn reset(&mut self) { + self.length = 0; + self.state.v0 = self.k0 ^ 0x736f6d6570736575; + self.state.v1 = self.k1 ^ 0x646f72616e646f6d; + self.state.v2 = self.k0 ^ 0x6c7967656e657261; + self.state.v3 = self.k1 ^ 0x7465646279746573; + self.ntail = 0; + } +} + +impl Hasher for SipHasher13 { + // Note: no integer hashing methods (`write_u*`, `write_i*`) are defined + // for this type. We could add them, copy the `short_write` implementation + // in librustc_data_structures/sip128.rs, and add `write_u*`/`write_i*` + // methods to `SipHasher`, `SipHasher13`, and `DefaultHasher`. This would + // greatly speed up integer hashing by those hashers, at the cost of + // slightly slowing down compile speeds on some benchmarks. See #69152 for + // details. + fn write(&mut self, msg: &[u8]) { + let length = msg.len(); + self.length += length; + + let mut needed = 0; + + if self.ntail != 0 { + needed = 8 - self.ntail; + // SAFETY: `cmp::min(length, needed)` is guaranteed to not be over `length` + self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << (8 * self.ntail); + if length < needed { + self.ntail += length; + return; + } else { + self.state.v3 ^= self.tail; + Sip13Rounds::c_rounds(&mut self.state); + self.state.v0 ^= self.tail; + self.ntail = 0; + } + } + + // Buffered tail is now flushed, process new input. + let len = length - needed; + let left = len & 0x7; // len % 8 + + let mut i = needed; + while i < len - left { + // SAFETY: because `len - left` is the biggest multiple of 8 under + // `len`, and because `i` starts at `needed` where `len` is `length - needed`, + // `i + 8` is guaranteed to be less than or equal to `length`. + let mi = unsafe { load_int_le!(msg, i, u64) }; + + self.state.v3 ^= mi; + Sip13Rounds::c_rounds(&mut self.state); + self.state.v0 ^= mi; + + i += 8; + } + + // SAFETY: `i` is now `needed + len.div_euclid(8) * 8`, + // so `i + left` = `needed + len` = `length`, which is by + // definition equal to `msg.len()`. + self.tail = unsafe { u8to64_le(msg, i, left) }; + self.ntail = left; + } + + fn finish(&self) -> u64 { + let mut state = self.state; + + let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail; + + state.v3 ^= b; + Sip13Rounds::c_rounds(&mut state); + state.v0 ^= b; + + state.v2 ^= 0xff; + Sip13Rounds::d_rounds(&mut state); + + state.v0 ^ state.v1 ^ state.v2 ^ state.v3 + } +} + +struct Sip13Rounds; + +impl Sip13Rounds { + fn c_rounds(state: &mut State) { + compress!(state); + } + + fn d_rounds(state: &mut State) { + compress!(state); + compress!(state); + compress!(state); + } +} diff --git a/vendor/cxx/src/symbols/exception.rs b/vendor/cxx/src/symbols/exception.rs new file mode 100644 index 000000000..b8fe1b5da --- /dev/null +++ b/vendor/cxx/src/symbols/exception.rs @@ -0,0 +1,18 @@ +#![cfg(feature = "alloc")] + +use crate::result::PtrLen; +use alloc::boxed::Box; +use alloc::string::String; +use core::ptr::NonNull; +use core::slice; + +#[export_name = "cxxbridge1$exception"] +unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> PtrLen { + let slice = unsafe { slice::from_raw_parts(ptr, len) }; + let string = String::from_utf8_lossy(slice); + let len = string.len(); + let raw_str = Box::into_raw(string.into_owned().into_boxed_str()); + let raw_u8 = raw_str.cast::<u8>(); + let nonnull = unsafe { NonNull::new_unchecked(raw_u8) }; + PtrLen { ptr: nonnull, len } +} diff --git a/vendor/cxx/src/symbols/mod.rs b/vendor/cxx/src/symbols/mod.rs new file mode 100644 index 000000000..e00bb550e --- /dev/null +++ b/vendor/cxx/src/symbols/mod.rs @@ -0,0 +1,5 @@ +mod exception; +mod rust_slice; +mod rust_str; +mod rust_string; +mod rust_vec; diff --git a/vendor/cxx/src/symbols/rust_slice.rs b/vendor/cxx/src/symbols/rust_slice.rs new file mode 100644 index 000000000..df215acf5 --- /dev/null +++ b/vendor/cxx/src/symbols/rust_slice.rs @@ -0,0 +1,20 @@ +use crate::rust_slice::RustSlice; +use core::mem::MaybeUninit; +use core::ptr::{self, NonNull}; + +#[export_name = "cxxbridge1$slice$new"] +unsafe extern "C" fn slice_new(this: &mut MaybeUninit<RustSlice>, ptr: NonNull<()>, len: usize) { + let this = this.as_mut_ptr(); + let rust_slice = RustSlice::from_raw_parts(ptr, len); + unsafe { ptr::write(this, rust_slice) } +} + +#[export_name = "cxxbridge1$slice$ptr"] +unsafe extern "C" fn slice_ptr(this: &RustSlice) -> NonNull<()> { + this.as_non_null_ptr() +} + +#[export_name = "cxxbridge1$slice$len"] +unsafe extern "C" fn slice_len(this: &RustSlice) -> usize { + this.len() +} diff --git a/vendor/cxx/src/symbols/rust_str.rs b/vendor/cxx/src/symbols/rust_str.rs new file mode 100644 index 000000000..3b33bc4a5 --- /dev/null +++ b/vendor/cxx/src/symbols/rust_str.rs @@ -0,0 +1,43 @@ +#[cfg(feature = "alloc")] +use alloc::string::String; +use core::mem::MaybeUninit; +use core::ptr; +use core::slice; +use core::str; + +#[export_name = "cxxbridge1$str$new"] +unsafe extern "C" fn str_new(this: &mut MaybeUninit<&str>) { + let this = this.as_mut_ptr(); + unsafe { ptr::write(this, "") } +} + +#[cfg(feature = "alloc")] +#[export_name = "cxxbridge1$str$ref"] +unsafe extern "C" fn str_ref<'a>(this: &mut MaybeUninit<&'a str>, string: &'a String) { + let this = this.as_mut_ptr(); + let s = string.as_str(); + unsafe { ptr::write(this, s) } +} + +#[export_name = "cxxbridge1$str$from"] +unsafe extern "C" fn str_from(this: &mut MaybeUninit<&str>, ptr: *const u8, len: usize) -> bool { + let slice = unsafe { slice::from_raw_parts(ptr, len) }; + match str::from_utf8(slice) { + Ok(s) => { + let this = this.as_mut_ptr(); + unsafe { ptr::write(this, s) } + true + } + Err(_) => false, + } +} + +#[export_name = "cxxbridge1$str$ptr"] +unsafe extern "C" fn str_ptr(this: &&str) -> *const u8 { + this.as_ptr() +} + +#[export_name = "cxxbridge1$str$len"] +unsafe extern "C" fn str_len(this: &&str) -> usize { + this.len() +} diff --git a/vendor/cxx/src/symbols/rust_string.rs b/vendor/cxx/src/symbols/rust_string.rs new file mode 100644 index 000000000..8b7c8c481 --- /dev/null +++ b/vendor/cxx/src/symbols/rust_string.rs @@ -0,0 +1,114 @@ +#![cfg(feature = "alloc")] + +use alloc::borrow::ToOwned; +use alloc::string::String; +use core::mem::{ManuallyDrop, MaybeUninit}; +use core::ptr; +use core::slice; +use core::str; + +#[export_name = "cxxbridge1$string$new"] +unsafe extern "C" fn string_new(this: &mut MaybeUninit<String>) { + let this = this.as_mut_ptr(); + let new = String::new(); + unsafe { ptr::write(this, new) } +} + +#[export_name = "cxxbridge1$string$clone"] +unsafe extern "C" fn string_clone(this: &mut MaybeUninit<String>, other: &String) { + let this = this.as_mut_ptr(); + let clone = other.clone(); + unsafe { ptr::write(this, clone) } +} + +#[export_name = "cxxbridge1$string$from_utf8"] +unsafe extern "C" fn string_from_utf8( + this: &mut MaybeUninit<String>, + ptr: *const u8, + len: usize, +) -> bool { + let slice = unsafe { slice::from_raw_parts(ptr, len) }; + match str::from_utf8(slice) { + Ok(s) => { + let this = this.as_mut_ptr(); + let owned = s.to_owned(); + unsafe { ptr::write(this, owned) } + true + } + Err(_) => false, + } +} + +#[export_name = "cxxbridge1$string$from_utf8_lossy"] +unsafe extern "C" fn string_from_utf8_lossy( + this: &mut MaybeUninit<String>, + ptr: *const u8, + len: usize, +) { + let slice = unsafe { slice::from_raw_parts(ptr, len) }; + let owned = String::from_utf8_lossy(slice).into_owned(); + let this = this.as_mut_ptr(); + unsafe { ptr::write(this, owned) } +} + +#[export_name = "cxxbridge1$string$from_utf16"] +unsafe extern "C" fn string_from_utf16( + this: &mut MaybeUninit<String>, + ptr: *const u16, + len: usize, +) -> bool { + let slice = unsafe { slice::from_raw_parts(ptr, len) }; + match String::from_utf16(slice) { + Ok(s) => { + let this = this.as_mut_ptr(); + unsafe { ptr::write(this, s) } + true + } + Err(_) => false, + } +} + +#[export_name = "cxxbridge1$string$from_utf16_lossy"] +unsafe extern "C" fn string_from_utf16_lossy( + this: &mut MaybeUninit<String>, + ptr: *const u16, + len: usize, +) { + let slice = unsafe { slice::from_raw_parts(ptr, len) }; + let owned = String::from_utf16_lossy(slice); + let this = this.as_mut_ptr(); + unsafe { ptr::write(this, owned) } +} + +#[export_name = "cxxbridge1$string$drop"] +unsafe extern "C" fn string_drop(this: &mut ManuallyDrop<String>) { + unsafe { ManuallyDrop::drop(this) } +} + +#[export_name = "cxxbridge1$string$ptr"] +unsafe extern "C" fn string_ptr(this: &String) -> *const u8 { + this.as_ptr() +} + +#[export_name = "cxxbridge1$string$len"] +unsafe extern "C" fn string_len(this: &String) -> usize { + this.len() +} + +#[export_name = "cxxbridge1$string$capacity"] +unsafe extern "C" fn string_capacity(this: &String) -> usize { + this.capacity() +} + +#[export_name = "cxxbridge1$string$reserve_additional"] +unsafe extern "C" fn string_reserve_additional(this: &mut String, additional: usize) { + this.reserve(additional); +} + +#[export_name = "cxxbridge1$string$reserve_total"] +unsafe extern "C" fn string_reserve_total(this: &mut String, new_cap: usize) { + if new_cap > this.capacity() { + let additional = new_cap - this.len(); + this.reserve(additional); + } +} diff --git a/vendor/cxx/src/symbols/rust_vec.rs b/vendor/cxx/src/symbols/rust_vec.rs new file mode 100644 index 000000000..89c7da44e --- /dev/null +++ b/vendor/cxx/src/symbols/rust_vec.rs @@ -0,0 +1,91 @@ +#![cfg(feature = "alloc")] + +use crate::c_char::c_char; +use crate::rust_string::RustString; +use crate::rust_vec::RustVec; +use alloc::vec::Vec; +use core::mem; +use core::ptr; + +macro_rules! rust_vec_shims { + ($segment:expr, $ty:ty) => { + const_assert_eq!(mem::size_of::<[usize; 3]>(), mem::size_of::<RustVec<$ty>>()); + const_assert_eq!(mem::size_of::<Vec<$ty>>(), mem::size_of::<RustVec<$ty>>()); + const_assert_eq!(mem::align_of::<Vec<$ty>>(), mem::align_of::<RustVec<$ty>>()); + + const _: () = { + attr! { + #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$new")] + unsafe extern "C" fn __new(this: *mut RustVec<$ty>) { + unsafe { ptr::write(this, RustVec::new()) } + } + } + attr! { + #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$drop")] + unsafe extern "C" fn __drop(this: *mut RustVec<$ty>) { + unsafe { ptr::drop_in_place(this) } + } + } + attr! { + #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$len")] + unsafe extern "C" fn __len(this: *const RustVec<$ty>) -> usize { + unsafe { &*this }.len() + } + } + attr! { + #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$capacity")] + unsafe extern "C" fn __capacity(this: *const RustVec<$ty>) -> usize { + unsafe { &*this }.capacity() + } + } + attr! { + #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$data")] + unsafe extern "C" fn __data(this: *const RustVec<$ty>) -> *const $ty { + unsafe { &*this }.as_ptr() + } + } + attr! { + #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$reserve_total")] + unsafe extern "C" fn __reserve_total(this: *mut RustVec<$ty>, new_cap: usize) { + unsafe { &mut *this }.reserve_total(new_cap); + } + } + attr! { + #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$set_len")] + unsafe extern "C" fn __set_len(this: *mut RustVec<$ty>, len: usize) { + unsafe { (*this).set_len(len) } + } + } + attr! { + #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$truncate")] + unsafe extern "C" fn __truncate(this: *mut RustVec<$ty>, len: usize) { + unsafe { (*this).truncate(len) } + } + } + }; + }; +} + +macro_rules! rust_vec_shims_for_primitive { + ($ty:ident) => { + rust_vec_shims!(stringify!($ty), $ty); + }; +} + +rust_vec_shims_for_primitive!(bool); +rust_vec_shims_for_primitive!(u8); +rust_vec_shims_for_primitive!(u16); +rust_vec_shims_for_primitive!(u32); +rust_vec_shims_for_primitive!(u64); +rust_vec_shims_for_primitive!(usize); +rust_vec_shims_for_primitive!(i8); +rust_vec_shims_for_primitive!(i16); +rust_vec_shims_for_primitive!(i32); +rust_vec_shims_for_primitive!(i64); +rust_vec_shims_for_primitive!(isize); +rust_vec_shims_for_primitive!(f32); +rust_vec_shims_for_primitive!(f64); + +rust_vec_shims!("char", c_char); +rust_vec_shims!("string", RustString); +rust_vec_shims!("str", &str); diff --git a/vendor/cxx/src/type_id.rs b/vendor/cxx/src/type_id.rs new file mode 100644 index 000000000..bd2b4ea61 --- /dev/null +++ b/vendor/cxx/src/type_id.rs @@ -0,0 +1,9 @@ +/// For use in impls of the `ExternType` trait. See [`ExternType`]. +/// +/// [`ExternType`]: trait.ExternType.html +#[macro_export] +macro_rules! type_id { + ($($path:tt)*) => { + $crate::private::type_id! { $crate $($path)* } + }; +} diff --git a/vendor/cxx/src/unique_ptr.rs b/vendor/cxx/src/unique_ptr.rs new file mode 100644 index 000000000..33992059e --- /dev/null +++ b/vendor/cxx/src/unique_ptr.rs @@ -0,0 +1,296 @@ +use crate::cxx_vector::{CxxVector, VectorElement}; +use crate::fmt::display; +use crate::kind::Trivial; +use crate::string::CxxString; +use crate::ExternType; +use core::ffi::c_void; +use core::fmt::{self, Debug, Display}; +use core::marker::PhantomData; +use core::mem::{self, MaybeUninit}; +use core::ops::{Deref, DerefMut}; +use core::pin::Pin; + +/// Binding to C++ `std::unique_ptr<T, std::default_delete<T>>`. +#[repr(C)] +pub struct UniquePtr<T> +where + T: UniquePtrTarget, +{ + repr: MaybeUninit<*mut c_void>, + ty: PhantomData<T>, +} + +impl<T> UniquePtr<T> +where + T: UniquePtrTarget, +{ + /// Makes a new UniquePtr wrapping a null pointer. + /// + /// Matches the behavior of default-constructing a std::unique\_ptr. + pub fn null() -> Self { + UniquePtr { + repr: T::__null(), + ty: PhantomData, + } + } + + /// Allocates memory on the heap and makes a UniquePtr pointing to it. + pub fn new(value: T) -> Self + where + T: ExternType<Kind = Trivial>, + { + UniquePtr { + repr: T::__new(value), + ty: PhantomData, + } + } + + /// Checks whether the UniquePtr does not own an object. + /// + /// This is the opposite of [std::unique_ptr\<T\>::operator bool](https://en.cppreference.com/w/cpp/memory/unique_ptr/operator_bool). + pub fn is_null(&self) -> bool { + let ptr = unsafe { T::__get(self.repr) }; + ptr.is_null() + } + + /// Returns a reference to the object owned by this UniquePtr if any, + /// otherwise None. + pub fn as_ref(&self) -> Option<&T> { + unsafe { T::__get(self.repr).as_ref() } + } + + /// Returns a mutable pinned reference to the object owned by this UniquePtr + /// if any, otherwise None. + pub fn as_mut(&mut self) -> Option<Pin<&mut T>> { + unsafe { + let mut_reference = (T::__get(self.repr) as *mut T).as_mut()?; + Some(Pin::new_unchecked(mut_reference)) + } + } + + /// Returns a mutable pinned reference to the object owned by this + /// UniquePtr. + /// + /// # Panics + /// + /// Panics if the UniquePtr holds a null pointer. + pub fn pin_mut(&mut self) -> Pin<&mut T> { + match self.as_mut() { + Some(target) => target, + None => panic!( + "called pin_mut on a null UniquePtr<{}>", + display(T::__typename), + ), + } + } + + /// Consumes the UniquePtr, releasing its ownership of the heap-allocated T. + /// + /// Matches the behavior of [std::unique_ptr\<T\>::release](https://en.cppreference.com/w/cpp/memory/unique_ptr/release). + pub fn into_raw(self) -> *mut T { + let ptr = unsafe { T::__release(self.repr) }; + mem::forget(self); + ptr + } + + /// Constructs a UniquePtr retaking ownership of a pointer previously + /// obtained from `into_raw`. + /// + /// # Safety + /// + /// This function is unsafe because improper use may lead to memory + /// problems. For example a double-free may occur if the function is called + /// twice on the same raw pointer. + pub unsafe fn from_raw(raw: *mut T) -> Self { + UniquePtr { + repr: unsafe { T::__raw(raw) }, + ty: PhantomData, + } + } +} + +unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {} +unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {} + +// UniquePtr is not a self-referential type and is safe to move out of a Pin, +// regardless whether the pointer's target is Unpin. +impl<T> Unpin for UniquePtr<T> where T: UniquePtrTarget {} + +impl<T> Drop for UniquePtr<T> +where + T: UniquePtrTarget, +{ + fn drop(&mut self) { + unsafe { T::__drop(self.repr) } + } +} + +impl<T> Deref for UniquePtr<T> +where + T: UniquePtrTarget, +{ + type Target = T; + + fn deref(&self) -> &Self::Target { + match self.as_ref() { + Some(target) => target, + None => panic!( + "called deref on a null UniquePtr<{}>", + display(T::__typename), + ), + } + } +} + +impl<T> DerefMut for UniquePtr<T> +where + T: UniquePtrTarget + Unpin, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + match self.as_mut() { + Some(target) => Pin::into_inner(target), + None => panic!( + "called deref_mut on a null UniquePtr<{}>", + display(T::__typename), + ), + } + } +} + +impl<T> Debug for UniquePtr<T> +where + T: Debug + UniquePtrTarget, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self.as_ref() { + None => formatter.write_str("nullptr"), + Some(value) => Debug::fmt(value, formatter), + } + } +} + +impl<T> Display for UniquePtr<T> +where + T: Display + UniquePtrTarget, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self.as_ref() { + None => formatter.write_str("nullptr"), + Some(value) => Display::fmt(value, formatter), + } + } +} + +/// Trait bound for types which may be used as the `T` inside of a +/// `UniquePtr<T>` in generic code. +/// +/// This trait has no publicly callable or implementable methods. Implementing +/// it outside of the CXX codebase is not supported. +/// +/// # Example +/// +/// A bound `T: UniquePtrTarget` may be necessary when manipulating +/// [`UniquePtr`] in generic code. +/// +/// ``` +/// use cxx::memory::{UniquePtr, UniquePtrTarget}; +/// use std::fmt::Display; +/// +/// pub fn take_generic_ptr<T>(ptr: UniquePtr<T>) +/// where +/// T: UniquePtrTarget + Display, +/// { +/// println!("the unique_ptr points to: {}", *ptr); +/// } +/// ``` +/// +/// Writing the same generic function without a `UniquePtrTarget` trait bound +/// would not compile. +pub unsafe trait UniquePtrTarget { + #[doc(hidden)] + fn __typename(f: &mut fmt::Formatter) -> fmt::Result; + #[doc(hidden)] + fn __null() -> MaybeUninit<*mut c_void>; + #[doc(hidden)] + fn __new(value: Self) -> MaybeUninit<*mut c_void> + where + Self: Sized, + { + // Opaque C types do not get this method because they can never exist by + // value on the Rust side of the bridge. + let _ = value; + unreachable!() + } + #[doc(hidden)] + unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void>; + #[doc(hidden)] + unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self; + #[doc(hidden)] + unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self; + #[doc(hidden)] + unsafe fn __drop(repr: MaybeUninit<*mut c_void>); +} + +extern "C" { + #[link_name = "cxxbridge1$unique_ptr$std$string$null"] + fn unique_ptr_std_string_null(this: *mut MaybeUninit<*mut c_void>); + #[link_name = "cxxbridge1$unique_ptr$std$string$raw"] + fn unique_ptr_std_string_raw(this: *mut MaybeUninit<*mut c_void>, raw: *mut CxxString); + #[link_name = "cxxbridge1$unique_ptr$std$string$get"] + fn unique_ptr_std_string_get(this: *const MaybeUninit<*mut c_void>) -> *const CxxString; + #[link_name = "cxxbridge1$unique_ptr$std$string$release"] + fn unique_ptr_std_string_release(this: *mut MaybeUninit<*mut c_void>) -> *mut CxxString; + #[link_name = "cxxbridge1$unique_ptr$std$string$drop"] + fn unique_ptr_std_string_drop(this: *mut MaybeUninit<*mut c_void>); +} + +unsafe impl UniquePtrTarget for CxxString { + fn __typename(f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("CxxString") + } + fn __null() -> MaybeUninit<*mut c_void> { + let mut repr = MaybeUninit::uninit(); + unsafe { + unique_ptr_std_string_null(&mut repr); + } + repr + } + unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> { + let mut repr = MaybeUninit::uninit(); + unsafe { unique_ptr_std_string_raw(&mut repr, raw) } + repr + } + unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self { + unsafe { unique_ptr_std_string_get(&repr) } + } + unsafe fn __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self { + unsafe { unique_ptr_std_string_release(&mut repr) } + } + unsafe fn __drop(mut repr: MaybeUninit<*mut c_void>) { + unsafe { unique_ptr_std_string_drop(&mut repr) } + } +} + +unsafe impl<T> UniquePtrTarget for CxxVector<T> +where + T: VectorElement, +{ + fn __typename(f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "CxxVector<{}>", display(T::__typename)) + } + fn __null() -> MaybeUninit<*mut c_void> { + T::__unique_ptr_null() + } + unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> { + unsafe { T::__unique_ptr_raw(raw) } + } + unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self { + unsafe { T::__unique_ptr_get(repr) } + } + unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self { + unsafe { T::__unique_ptr_release(repr) } + } + unsafe fn __drop(repr: MaybeUninit<*mut c_void>) { + unsafe { T::__unique_ptr_drop(repr) } + } +} diff --git a/vendor/cxx/src/unwind.rs b/vendor/cxx/src/unwind.rs new file mode 100644 index 000000000..18852da71 --- /dev/null +++ b/vendor/cxx/src/unwind.rs @@ -0,0 +1,39 @@ +#![allow(missing_docs)] + +use core::mem; + +pub fn prevent_unwind<F, R>(label: &'static str, foreign_call: F) -> R +where + F: FnOnce() -> R, +{ + // Goal is to make it impossible to propagate a panic across the C interface + // of an extern "Rust" function, which would be Undefined Behavior. We + // transform such panicks into a deterministic abort instead. When cxx is + // built in an application using panic=abort, this guard object is compiled + // out because its destructor is statically unreachable. When built with + // panic=unwind, an unwind from the foreign call will attempt to drop the + // guard object leading to a double panic, which is defined by Rust to + // abort. In no_std programs, on most platforms the current mechanism for + // this is for core::intrinsics::abort to invoke an invalid instruction. On + // Unix, the process will probably terminate with a signal like SIGABRT, + // SIGILL, SIGTRAP, SIGSEGV or SIGBUS. The precise behaviour is not + // guaranteed and not stable, but is safe. + let guard = Guard { label }; + + let ret = foreign_call(); + + // If we made it here, no uncaught panic occurred during the foreign call. + mem::forget(guard); + ret +} + +struct Guard { + label: &'static str, +} + +impl Drop for Guard { + #[cold] + fn drop(&mut self) { + panic!("panic in ffi function {}, aborting.", self.label); + } +} diff --git a/vendor/cxx/src/vector.rs b/vendor/cxx/src/vector.rs new file mode 100644 index 000000000..4afd4879a --- /dev/null +++ b/vendor/cxx/src/vector.rs @@ -0,0 +1,9 @@ +//! Less used details of `CxxVector`. +//! +//! `CxxVector` itself is exposed at the crate root. + +pub use crate::cxx_vector::{Iter, IterMut, VectorElement}; +#[doc(inline)] +pub use crate::Vector; +#[doc(no_inline)] +pub use cxx::CxxVector; diff --git a/vendor/cxx/src/weak_ptr.rs b/vendor/cxx/src/weak_ptr.rs new file mode 100644 index 000000000..e9320f374 --- /dev/null +++ b/vendor/cxx/src/weak_ptr.rs @@ -0,0 +1,189 @@ +use crate::shared_ptr::{SharedPtr, SharedPtrTarget}; +use crate::string::CxxString; +use core::ffi::c_void; +use core::fmt::{self, Debug}; +use core::marker::PhantomData; +use core::mem::MaybeUninit; + +/// Binding to C++ `std::weak_ptr<T>`. +/// +/// The typical way to construct a WeakPtr from Rust is by [downgrading] from a +/// SharedPtr. +/// +/// [downgrading]: crate::SharedPtr::downgrade +#[repr(C)] +pub struct WeakPtr<T> +where + T: WeakPtrTarget, +{ + repr: [MaybeUninit<*mut c_void>; 2], + ty: PhantomData<T>, +} + +impl<T> WeakPtr<T> +where + T: WeakPtrTarget, +{ + /// Makes a new WeakPtr wrapping a null pointer. + /// + /// Matches the behavior of default-constructing a std::weak\_ptr. + pub fn null() -> Self { + let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit(); + let new = weak_ptr.as_mut_ptr().cast(); + unsafe { + T::__null(new); + weak_ptr.assume_init() + } + } + + /// Upgrades a non-owning reference into an owning reference if possible, + /// otherwise to a null reference. + /// + /// Matches the behavior of [std::weak_ptr\<T\>::lock](https://en.cppreference.com/w/cpp/memory/weak_ptr/lock). + pub fn upgrade(&self) -> SharedPtr<T> + where + T: SharedPtrTarget, + { + let this = self as *const Self as *const c_void; + let mut shared_ptr = MaybeUninit::<SharedPtr<T>>::uninit(); + let new = shared_ptr.as_mut_ptr().cast(); + unsafe { + T::__upgrade(this, new); + shared_ptr.assume_init() + } + } +} + +unsafe impl<T> Send for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {} +unsafe impl<T> Sync for WeakPtr<T> where T: Send + Sync + WeakPtrTarget {} + +impl<T> Clone for WeakPtr<T> +where + T: WeakPtrTarget, +{ + fn clone(&self) -> Self { + let mut weak_ptr = MaybeUninit::<WeakPtr<T>>::uninit(); + let new = weak_ptr.as_mut_ptr().cast(); + let this = self as *const Self as *mut c_void; + unsafe { + T::__clone(this, new); + weak_ptr.assume_init() + } + } +} + +impl<T> Drop for WeakPtr<T> +where + T: WeakPtrTarget, +{ + fn drop(&mut self) { + let this = self as *mut Self as *mut c_void; + unsafe { T::__drop(this) } + } +} + +impl<T> Debug for WeakPtr<T> +where + T: Debug + WeakPtrTarget + SharedPtrTarget, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(&self.upgrade(), formatter) + } +} + +/// Trait bound for types which may be used as the `T` inside of a `WeakPtr<T>` +/// in generic code. +/// +/// This trait has no publicly callable or implementable methods. Implementing +/// it outside of the CXX codebase is not supported. +pub unsafe trait WeakPtrTarget { + #[doc(hidden)] + fn __typename(f: &mut fmt::Formatter) -> fmt::Result; + #[doc(hidden)] + unsafe fn __null(new: *mut c_void); + #[doc(hidden)] + unsafe fn __clone(this: *const c_void, new: *mut c_void); + #[doc(hidden)] + unsafe fn __downgrade(shared: *const c_void, new: *mut c_void); + #[doc(hidden)] + unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void); + #[doc(hidden)] + unsafe fn __drop(this: *mut c_void); +} + +macro_rules! impl_weak_ptr_target { + ($segment:expr, $name:expr, $ty:ty) => { + unsafe impl WeakPtrTarget for $ty { + fn __typename(f: &mut fmt::Formatter) -> fmt::Result { + f.write_str($name) + } + unsafe fn __null(new: *mut c_void) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$null")] + fn __null(new: *mut c_void); + } + } + unsafe { __null(new) } + } + unsafe fn __clone(this: *const c_void, new: *mut c_void) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$clone")] + fn __clone(this: *const c_void, new: *mut c_void); + } + } + unsafe { __clone(this, new) } + } + unsafe fn __downgrade(shared: *const c_void, weak: *mut c_void) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$downgrade")] + fn __downgrade(shared: *const c_void, weak: *mut c_void); + } + } + unsafe { __downgrade(shared, weak) } + } + unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$upgrade")] + fn __upgrade(weak: *const c_void, shared: *mut c_void); + } + } + unsafe { __upgrade(weak, shared) } + } + unsafe fn __drop(this: *mut c_void) { + extern "C" { + attr! { + #[link_name = concat!("cxxbridge1$std$weak_ptr$", $segment, "$drop")] + fn __drop(this: *mut c_void); + } + } + unsafe { __drop(this) } + } + } + }; +} + +macro_rules! impl_weak_ptr_target_for_primitive { + ($ty:ident) => { + impl_weak_ptr_target!(stringify!($ty), stringify!($ty), $ty); + }; +} + +impl_weak_ptr_target_for_primitive!(bool); +impl_weak_ptr_target_for_primitive!(u8); +impl_weak_ptr_target_for_primitive!(u16); +impl_weak_ptr_target_for_primitive!(u32); +impl_weak_ptr_target_for_primitive!(u64); +impl_weak_ptr_target_for_primitive!(usize); +impl_weak_ptr_target_for_primitive!(i8); +impl_weak_ptr_target_for_primitive!(i16); +impl_weak_ptr_target_for_primitive!(i32); +impl_weak_ptr_target_for_primitive!(i64); +impl_weak_ptr_target_for_primitive!(isize); +impl_weak_ptr_target_for_primitive!(f32); +impl_weak_ptr_target_for_primitive!(f64); + +impl_weak_ptr_target!("string", "CxxString", CxxString); diff --git a/vendor/cxx/tests/BUCK b/vendor/cxx/tests/BUCK new file mode 100644 index 000000000..865eebc93 --- /dev/null +++ b/vendor/cxx/tests/BUCK @@ -0,0 +1,57 @@ +load("//tools/buck:rust_cxx_bridge.bzl", "rust_cxx_bridge") + +rust_test( + name = "test", + srcs = ["test.rs"], + edition = "2018", + deps = [ + ":ffi", + "//:cxx", + ], +) + +rust_library( + name = "ffi", + srcs = [ + "ffi/cast.rs", + "ffi/lib.rs", + "ffi/module.rs", + ], + crate = "cxx_test_suite", + edition = "2018", + deps = [ + ":impl", + "//:cxx", + ], +) + +cxx_library( + name = "impl", + srcs = [ + "ffi/tests.cc", + ":bridge/source", + ":module/source", + ], + exported_deps = ["//:core"], + exported_headers = { + "ffi/lib.rs.h": ":bridge/header", + "ffi/module.rs.h": ":module/header", + "ffi/tests.h": "ffi/tests.h", + }, +) + +rust_cxx_bridge( + name = "bridge", + src = "ffi/lib.rs", + deps = [ + ":impl", + ], +) + +rust_cxx_bridge( + name = "module", + src = "ffi/module.rs", + deps = [ + ":impl", + ], +) diff --git a/vendor/cxx/tests/BUILD b/vendor/cxx/tests/BUILD new file mode 100644 index 000000000..3c25d9633 --- /dev/null +++ b/vendor/cxx/tests/BUILD @@ -0,0 +1,55 @@ +load("@rules_cc//cc:defs.bzl", "cc_library") +load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") +load("//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge") + +rust_test( + name = "test", + size = "small", + srcs = ["test.rs"], + edition = "2018", + deps = [ + ":cxx_test_suite", + "//:cxx", + ], +) + +rust_library( + name = "cxx_test_suite", + srcs = [ + "ffi/cast.rs", + "ffi/lib.rs", + "ffi/module.rs", + ], + edition = "2018", + deps = [ + ":impl", + "//:cxx", + ], +) + +cc_library( + name = "impl", + srcs = [ + "ffi/tests.cc", + ":bridge/source", + ":module/source", + ], + hdrs = ["ffi/tests.h"], + deps = [ + ":bridge/include", + ":module/include", + "//:core", + ], +) + +rust_cxx_bridge( + name = "bridge", + src = "ffi/lib.rs", + deps = [":impl"], +) + +rust_cxx_bridge( + name = "module", + src = "ffi/module.rs", + deps = [":impl"], +) diff --git a/vendor/cxx/tests/compiletest.rs b/vendor/cxx/tests/compiletest.rs new file mode 100644 index 000000000..cd58514f1 --- /dev/null +++ b/vendor/cxx/tests/compiletest.rs @@ -0,0 +1,9 @@ +#[allow(unused_attributes)] +#[rustversion::attr(not(nightly), ignore)] +#[cfg_attr(skip_ui_tests, ignore)] +#[cfg_attr(miri, ignore)] +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/*.rs"); +} diff --git a/vendor/cxx/tests/cxx_gen.rs b/vendor/cxx/tests/cxx_gen.rs new file mode 100644 index 000000000..e91675d9d --- /dev/null +++ b/vendor/cxx/tests/cxx_gen.rs @@ -0,0 +1,34 @@ +#![allow(clippy::field_reassign_with_default)] + +use cxx_gen::{generate_header_and_cc, Opt}; +use std::str; + +const BRIDGE0: &str = r#" + #[cxx::bridge] + mod ffi { + unsafe extern "C++" { + pub fn do_cpp_thing(foo: &str); + } + } +"#; + +#[test] +fn test_extern_c_function() { + let opt = Opt::default(); + let source = BRIDGE0.parse().unwrap(); + let generated = generate_header_and_cc(source, &opt).unwrap(); + let output = str::from_utf8(&generated.implementation).unwrap(); + // To avoid continual breakage we won't test every byte. + // Let's look for the major features. + assert!(output.contains("void cxxbridge1$do_cpp_thing(::rust::Str foo)")); +} + +#[test] +fn test_impl_annotation() { + let mut opt = Opt::default(); + opt.cxx_impl_annotations = Some("ANNOTATION".to_owned()); + let source = BRIDGE0.parse().unwrap(); + let generated = generate_header_and_cc(source, &opt).unwrap(); + let output = str::from_utf8(&generated.implementation).unwrap(); + assert!(output.contains("ANNOTATION void cxxbridge1$do_cpp_thing(::rust::Str foo)")); +} diff --git a/vendor/cxx/tests/cxx_string.rs b/vendor/cxx/tests/cxx_string.rs new file mode 100644 index 000000000..349a4e1f1 --- /dev/null +++ b/vendor/cxx/tests/cxx_string.rs @@ -0,0 +1,41 @@ +use cxx::{let_cxx_string, CxxString}; +use std::fmt::Write as _; + +#[test] +fn test_async_cxx_string() { + async fn f() { + let_cxx_string!(s = "..."); + + async fn g(_: &CxxString) {} + g(&s).await; + } + + // https://github.com/dtolnay/cxx/issues/693 + fn assert_send(_: impl Send) {} + assert_send(f()); +} + +#[test] +fn test_debug() { + let_cxx_string!(s = "x\"y\'z"); + + assert_eq!(format!("{:?}", s), r#""x\"y'z""#); +} + +#[test] +fn test_fmt_write() { + let_cxx_string!(s = ""); + + let name = "world"; + write!(s, "Hello, {name}!").unwrap(); + assert_eq!(s.to_str(), Ok("Hello, world!")); +} + +#[test] +fn test_io_write() { + let_cxx_string!(s = ""); + let mut reader: &[u8] = b"Hello, world!"; + + std::io::copy(&mut reader, &mut s).unwrap(); + assert_eq!(s.to_str(), Ok("Hello, world!")); +} diff --git a/vendor/cxx/tests/test.rs b/vendor/cxx/tests/test.rs new file mode 100644 index 000000000..bcf0a2cd1 --- /dev/null +++ b/vendor/cxx/tests/test.rs @@ -0,0 +1,380 @@ +#![allow( + clippy::assertions_on_constants, + clippy::assertions_on_result_states, + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::float_cmp, + clippy::needless_pass_by_value, + clippy::unit_cmp, + clippy::unseparated_literal_suffix +)] + +use cxx::SharedPtr; +use cxx_test_suite::module::ffi2; +use cxx_test_suite::{cast, ffi, R}; +use std::cell::Cell; +use std::ffi::CStr; + +thread_local! { + static CORRECT: Cell<bool> = Cell::new(false); +} + +#[no_mangle] +extern "C" fn cxx_test_suite_set_correct() { + CORRECT.with(|correct| correct.set(true)); +} + +macro_rules! check { + ($run:expr) => {{ + CORRECT.with(|correct| correct.set(false)); + $run; + assert!(CORRECT.with(Cell::get), "{}", stringify!($run)); + }}; +} + +#[test] +fn test_c_return() { + let shared = ffi::Shared { z: 2020 }; + let ns_shared = ffi::AShared { z: 2020 }; + let nested_ns_shared = ffi::ABShared { z: 2020 }; + + assert_eq!(2020, ffi::c_return_primitive()); + assert_eq!(2020, ffi::c_return_shared().z); + assert_eq!(2020, ffi::c_return_box().0); + ffi::c_return_unique_ptr(); + ffi2::c_return_ns_unique_ptr(); + assert_eq!(2020, *ffi::c_return_ref(&shared)); + assert_eq!(2020, *ffi::c_return_ns_ref(&ns_shared)); + assert_eq!(2020, *ffi::c_return_nested_ns_ref(&nested_ns_shared)); + assert_eq!("2020", ffi::c_return_str(&shared)); + assert_eq!( + b"2020\0", + cast::c_char_to_unsigned(ffi::c_return_slice_char(&shared)), + ); + assert_eq!("2020", ffi::c_return_rust_string()); + assert_eq!("Hello \u{fffd}World", ffi::c_return_rust_string_lossy()); + assert_eq!("2020", ffi::c_return_unique_ptr_string().to_str().unwrap()); + assert_eq!(4, ffi::c_return_unique_ptr_vector_u8().len()); + assert_eq!( + 200_u8, + ffi::c_return_unique_ptr_vector_u8().into_iter().sum(), + ); + assert_eq!( + 200.5_f64, + ffi::c_return_unique_ptr_vector_f64().into_iter().sum(), + ); + assert_eq!(2, ffi::c_return_unique_ptr_vector_shared().len()); + assert_eq!( + 2021_usize, + ffi::c_return_unique_ptr_vector_shared() + .into_iter() + .map(|o| o.z) + .sum(), + ); + assert_eq!(b"\x02\0\x02\0"[..], ffi::c_return_rust_vec_u8()); + assert_eq!([true, true, false][..], ffi::c_return_rust_vec_bool()); + assert_eq!(2020, ffi::c_return_identity(2020)); + assert_eq!(2021, ffi::c_return_sum(2020, 1)); + match ffi::c_return_enum(0) { + enm @ ffi::Enum::AVal => assert_eq!(0, enm.repr), + _ => assert!(false), + } + match ffi::c_return_enum(1) { + enm @ ffi::Enum::BVal => assert_eq!(2020, enm.repr), + _ => assert!(false), + } + match ffi::c_return_enum(2021) { + enm @ ffi::Enum::LastVal => assert_eq!(2021, enm.repr), + _ => assert!(false), + } + match ffi::c_return_ns_enum(0) { + enm @ ffi::AEnum::AAVal => assert_eq!(0, enm.repr), + _ => assert!(false), + } + match ffi::c_return_nested_ns_enum(0) { + enm @ ffi::ABEnum::ABAVal => assert_eq!(0, enm.repr), + _ => assert!(false), + } +} + +#[test] +fn test_c_try_return() { + assert_eq!((), ffi::c_try_return_void().unwrap()); + assert_eq!(2020, ffi::c_try_return_primitive().unwrap()); + assert_eq!( + "logic error", + ffi::c_fail_return_primitive().unwrap_err().what(), + ); + assert_eq!(2020, ffi::c_try_return_box().unwrap().0); + assert_eq!("2020", *ffi::c_try_return_ref(&"2020".to_owned()).unwrap()); + assert_eq!("2020", ffi::c_try_return_str("2020").unwrap()); + assert_eq!(b"2020", ffi::c_try_return_sliceu8(b"2020").unwrap()); + assert_eq!("2020", ffi::c_try_return_rust_string().unwrap()); + assert_eq!("2020", &*ffi::c_try_return_unique_ptr_string().unwrap()); +} + +#[test] +fn test_c_take() { + let unique_ptr = ffi::c_return_unique_ptr(); + let unique_ptr_ns = ffi2::c_return_ns_unique_ptr(); + + check!(ffi::c_take_primitive(2020)); + check!(ffi::c_take_shared(ffi::Shared { z: 2020 })); + check!(ffi::c_take_ns_shared(ffi::AShared { z: 2020 })); + check!(ffi::ns_c_take_ns_shared(ffi::AShared { z: 2020 })); + check!(ffi::c_take_nested_ns_shared(ffi::ABShared { z: 2020 })); + check!(ffi::c_take_box(Box::new(R(2020)))); + check!(ffi::c_take_ref_c(&unique_ptr)); + check!(ffi2::c_take_ref_ns_c(&unique_ptr_ns)); + check!(cxx_test_suite::module::ffi::c_take_unique_ptr(unique_ptr)); + check!(ffi::c_take_str("2020")); + check!(ffi::c_take_slice_char(cast::unsigned_to_c_char(b"2020"))); + check!(ffi::c_take_slice_shared(&[ + ffi::Shared { z: 2020 }, + ffi::Shared { z: 2021 }, + ])); + let shared_sort_slice = &mut [ + ffi::Shared { z: 2 }, + ffi::Shared { z: 0 }, + ffi::Shared { z: 7 }, + ffi::Shared { z: 4 }, + ]; + check!(ffi::c_take_slice_shared_sort(shared_sort_slice)); + assert_eq!(shared_sort_slice[0].z, 0); + assert_eq!(shared_sort_slice[1].z, 2); + assert_eq!(shared_sort_slice[2].z, 4); + assert_eq!(shared_sort_slice[3].z, 7); + let r_sort_slice = &mut [R(2020), R(2050), R(2021)]; + check!(ffi::c_take_slice_r(r_sort_slice)); + check!(ffi::c_take_slice_r_sort(r_sort_slice)); + assert_eq!(r_sort_slice[0].0, 2020); + assert_eq!(r_sort_slice[1].0, 2021); + assert_eq!(r_sort_slice[2].0, 2050); + check!(ffi::c_take_rust_string("2020".to_owned())); + check!(ffi::c_take_unique_ptr_string( + ffi::c_return_unique_ptr_string() + )); + let mut vector = ffi::c_return_unique_ptr_vector_u8(); + assert_eq!(vector.pin_mut().pop(), Some(9)); + check!(ffi::c_take_unique_ptr_vector_u8(vector)); + let mut vector = ffi::c_return_unique_ptr_vector_f64(); + vector.pin_mut().push(9.0); + check!(ffi::c_take_unique_ptr_vector_f64(vector)); + let mut vector = ffi::c_return_unique_ptr_vector_shared(); + vector.pin_mut().push(ffi::Shared { z: 9 }); + check!(ffi::c_take_unique_ptr_vector_shared(vector)); + check!(ffi::c_take_ref_vector(&ffi::c_return_unique_ptr_vector_u8())); + let test_vec = [86_u8, 75_u8, 30_u8, 9_u8].to_vec(); + check!(ffi::c_take_rust_vec(test_vec.clone())); + check!(ffi::c_take_rust_vec_index(test_vec.clone())); + let shared_test_vec = vec![ffi::Shared { z: 1010 }, ffi::Shared { z: 1011 }]; + check!(ffi::c_take_rust_vec_shared(shared_test_vec.clone())); + check!(ffi::c_take_rust_vec_shared_index(shared_test_vec.clone())); + check!(ffi::c_take_rust_vec_shared_push(shared_test_vec.clone())); + check!(ffi::c_take_rust_vec_shared_truncate( + shared_test_vec.clone() + )); + check!(ffi::c_take_rust_vec_shared_clear(shared_test_vec.clone())); + check!(ffi::c_take_rust_vec_shared_forward_iterator( + shared_test_vec, + )); + let shared_sort_vec = vec![ + ffi::Shared { z: 2 }, + ffi::Shared { z: 0 }, + ffi::Shared { z: 7 }, + ffi::Shared { z: 4 }, + ]; + check!(ffi::c_take_rust_vec_shared_sort(shared_sort_vec)); + check!(ffi::c_take_ref_rust_vec(&test_vec)); + check!(ffi::c_take_ref_rust_vec_index(&test_vec)); + check!(ffi::c_take_ref_rust_vec_copy(&test_vec)); + check!(ffi::c_take_ref_shared_string(&ffi::SharedString { + msg: "2020".to_owned() + })); + let ns_shared_test_vec = vec![ffi::AShared { z: 1010 }, ffi::AShared { z: 1011 }]; + check!(ffi::c_take_rust_vec_ns_shared(ns_shared_test_vec)); + let nested_ns_shared_test_vec = vec![ffi::ABShared { z: 1010 }, ffi::ABShared { z: 1011 }]; + check!(ffi::c_take_rust_vec_nested_ns_shared( + nested_ns_shared_test_vec + )); + + check!(ffi::c_take_enum(ffi::Enum::AVal)); + check!(ffi::c_take_ns_enum(ffi::AEnum::AAVal)); + check!(ffi::c_take_nested_ns_enum(ffi::ABEnum::ABAVal)); +} + +#[test] +fn test_c_callback() { + fn callback(s: String) -> usize { + if s == "2020" { + cxx_test_suite_set_correct(); + } + 0 + } + + #[allow(clippy::ptr_arg)] + fn callback_ref(s: &String) { + if s == "2020" { + cxx_test_suite_set_correct(); + } + } + + fn callback_mut(s: &mut String) { + if s == "2020" { + cxx_test_suite_set_correct(); + } + } + + check!(ffi::c_take_callback(callback)); + check!(ffi::c_take_callback_ref(callback_ref)); + check!(ffi::c_take_callback_ref_lifetime(callback_ref)); + check!(ffi::c_take_callback_mut(callback_mut)); +} + +#[test] +fn test_c_call_r() { + fn cxx_run_test() { + extern "C" { + fn cxx_run_test() -> *const i8; + } + let failure = unsafe { cxx_run_test() }; + if !failure.is_null() { + let msg = unsafe { CStr::from_ptr(failure as *mut std::os::raw::c_char) }; + eprintln!("{}", msg.to_string_lossy()); + } + } + check!(cxx_run_test()); +} + +#[test] +fn test_c_method_calls() { + let mut unique_ptr = ffi::c_return_unique_ptr(); + + let old_value = unique_ptr.get(); + assert_eq!(2020, old_value); + assert_eq!(2021, unique_ptr.pin_mut().set(2021)); + assert_eq!(2021, unique_ptr.get()); + assert_eq!(2021, unique_ptr.get2()); + assert_eq!(2021, *unique_ptr.getRef()); + assert_eq!(2021, *unique_ptr.pin_mut().getMut()); + assert_eq!(2022, unique_ptr.pin_mut().set_succeed(2022).unwrap()); + assert!(unique_ptr.pin_mut().get_fail().is_err()); + assert_eq!(2021, ffi::Shared { z: 0 }.c_method_on_shared()); + assert_eq!(2022, *ffi::Shared { z: 2022 }.c_method_ref_on_shared()); + assert_eq!(2023, *ffi::Shared { z: 2023 }.c_method_mut_on_shared()); + + let val = 42; + let mut array = ffi::Array { + a: [0, 0, 0, 0], + b: ffi::Buffer::default(), + }; + array.c_set_array(val); + assert_eq!(array.a.len() as i32 * val, array.r_get_array_sum()); +} + +#[test] +fn test_shared_ptr_weak_ptr() { + let shared_ptr = ffi::c_return_shared_ptr(); + let weak_ptr = SharedPtr::downgrade(&shared_ptr); + assert_eq!(1, ffi::c_get_use_count(&weak_ptr)); + + assert!(!weak_ptr.upgrade().is_null()); + assert_eq!(1, ffi::c_get_use_count(&weak_ptr)); + + drop(shared_ptr); + assert_eq!(0, ffi::c_get_use_count(&weak_ptr)); + assert!(weak_ptr.upgrade().is_null()); +} + +#[test] +fn test_c_ns_method_calls() { + let unique_ptr = ffi2::ns_c_return_unique_ptr_ns(); + + let old_value = unique_ptr.get(); + assert_eq!(1000, old_value); +} + +#[test] +fn test_enum_representations() { + assert_eq!(0, ffi::Enum::AVal.repr); + assert_eq!(2020, ffi::Enum::BVal.repr); + assert_eq!(2021, ffi::Enum::LastVal.repr); +} + +#[test] +fn test_debug() { + assert_eq!("Shared { z: 1 }", format!("{:?}", ffi::Shared { z: 1 })); + assert_eq!("BVal", format!("{:?}", ffi::Enum::BVal)); + assert_eq!("Enum(9)", format!("{:?}", ffi::Enum { repr: 9 })); +} + +#[no_mangle] +extern "C" fn cxx_test_suite_get_box() -> *mut R { + Box::into_raw(Box::new(R(2020usize))) +} + +#[no_mangle] +unsafe extern "C" fn cxx_test_suite_r_is_correct(r: *const R) -> bool { + (*r).0 == 2020 +} + +#[test] +fn test_rust_name_attribute() { + assert_eq!("2020", ffi::i32_overloaded_function(2020)); + assert_eq!("2020", ffi::str_overloaded_function("2020")); + let unique_ptr = ffi::c_return_unique_ptr(); + assert_eq!("2020", unique_ptr.i32_overloaded_method(2020)); + assert_eq!("2020", unique_ptr.str_overloaded_method("2020")); +} + +#[test] +fn test_extern_trivial() { + let mut d = ffi2::c_return_trivial(); + check!(ffi2::c_take_trivial_ref(&d)); + check!(d.c_take_trivial_ref_method()); + check!(d.c_take_trivial_mut_ref_method()); + check!(ffi2::c_take_trivial(d)); + let mut d = ffi2::c_return_trivial_ptr(); + check!(d.c_take_trivial_ref_method()); + check!(d.c_take_trivial_mut_ref_method()); + check!(ffi2::c_take_trivial_ptr(d)); + cxx::UniquePtr::new(ffi2::D { d: 42 }); + let d = ffi2::ns_c_return_trivial(); + check!(ffi2::ns_c_take_trivial(d)); + + let g = ffi2::c_return_trivial_ns(); + check!(ffi2::c_take_trivial_ns_ref(&g)); + check!(ffi2::c_take_trivial_ns(g)); + let g = ffi2::c_return_trivial_ns_ptr(); + check!(ffi2::c_take_trivial_ns_ptr(g)); + cxx::UniquePtr::new(ffi2::G { g: 42 }); +} + +#[test] +fn test_extern_opaque() { + let mut e = ffi2::c_return_opaque_ptr(); + check!(ffi2::c_take_opaque_ref(e.as_ref().unwrap())); + check!(e.c_take_opaque_ref_method()); + check!(e.pin_mut().c_take_opaque_mut_ref_method()); + check!(ffi2::c_take_opaque_ptr(e)); + + let f = ffi2::c_return_ns_opaque_ptr(); + check!(ffi2::c_take_opaque_ns_ref(f.as_ref().unwrap())); + check!(ffi2::c_take_opaque_ns_ptr(f)); +} + +#[test] +fn test_raw_ptr() { + let c = ffi::c_return_mut_ptr(2023); + let mut c_unique = unsafe { cxx::UniquePtr::from_raw(c) }; + assert_eq!(2023, c_unique.pin_mut().set_succeed(2023).unwrap()); + // c will be dropped as it's now in a UniquePtr + + let c2 = ffi::c_return_mut_ptr(2024); + assert_eq!(2024, unsafe { ffi::c_take_const_ptr(c2) }); + assert_eq!(2024, unsafe { ffi::c_take_mut_ptr(c2) }); // deletes c2 + + let c3 = ffi::c_return_const_ptr(2025); + assert_eq!(2025, unsafe { ffi::c_take_const_ptr(c3) }); + assert_eq!(2025, unsafe { ffi::c_take_mut_ptr(c3 as *mut ffi::C) }); // deletes c3 +} diff --git a/vendor/cxx/tests/ui/array_len_expr.rs b/vendor/cxx/tests/ui/array_len_expr.rs new file mode 100644 index 000000000..73da57c8f --- /dev/null +++ b/vendor/cxx/tests/ui/array_len_expr.rs @@ -0,0 +1,10 @@ +#[cxx::bridge] +mod ffi { + struct Shared { + arraystr: [String; "13"], + arraysub: [String; 15 - 1], + arrayzero: [String; 0], + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/array_len_expr.stderr b/vendor/cxx/tests/ui/array_len_expr.stderr new file mode 100644 index 000000000..c58cfbc2c --- /dev/null +++ b/vendor/cxx/tests/ui/array_len_expr.stderr @@ -0,0 +1,17 @@ +error: array length must be an integer literal + --> tests/ui/array_len_expr.rs:4:28 + | +4 | arraystr: [String; "13"], + | ^^^^ + +error: unsupported expression, array length must be an integer literal + --> tests/ui/array_len_expr.rs:5:28 + | +5 | arraysub: [String; 15 - 1], + | ^^^^^^ + +error: array with zero size is not supported + --> tests/ui/array_len_expr.rs:6:20 + | +6 | arrayzero: [String; 0], + | ^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/array_len_suffix.rs b/vendor/cxx/tests/ui/array_len_suffix.rs new file mode 100644 index 000000000..1e9d514fc --- /dev/null +++ b/vendor/cxx/tests/ui/array_len_suffix.rs @@ -0,0 +1,8 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + fn array() -> [String; 12u16]; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/array_len_suffix.stderr b/vendor/cxx/tests/ui/array_len_suffix.stderr new file mode 100644 index 000000000..1dde790e8 --- /dev/null +++ b/vendor/cxx/tests/ui/array_len_suffix.stderr @@ -0,0 +1,10 @@ +error[E0308]: mismatched types + --> tests/ui/array_len_suffix.rs:4:32 + | +4 | fn array() -> [String; 12u16]; + | ^^^^^ expected `usize`, found `u16` + | +help: change the type of the numeric literal from `u16` to `usize` + | +4 | fn array() -> [String; 12usize]; + | ~~~~~ diff --git a/vendor/cxx/tests/ui/async_fn.rs b/vendor/cxx/tests/ui/async_fn.rs new file mode 100644 index 000000000..4e663a0b6 --- /dev/null +++ b/vendor/cxx/tests/ui/async_fn.rs @@ -0,0 +1,14 @@ +#[cxx::bridge] +mod ffi { + extern "Rust" { + async fn f(); + } + + extern "C++" { + async fn g(); + } +} + +async fn f() {} + +fn main() {} diff --git a/vendor/cxx/tests/ui/async_fn.stderr b/vendor/cxx/tests/ui/async_fn.stderr new file mode 100644 index 000000000..78108650f --- /dev/null +++ b/vendor/cxx/tests/ui/async_fn.stderr @@ -0,0 +1,11 @@ +error: async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach, and https://github.com/pcwalton/cxx-async for some helpers; eventually what you wrote will work but it isn't integrated into the cxx::bridge macro yet + --> tests/ui/async_fn.rs:4:9 + | +4 | async fn f(); + | ^^^^^^^^^^^^^ + +error: async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach, and https://github.com/pcwalton/cxx-async for some helpers; eventually what you wrote will work but it isn't integrated into the cxx::bridge macro yet + --> tests/ui/async_fn.rs:8:9 + | +8 | async fn g(); + | ^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/bad_explicit_impl.rs b/vendor/cxx/tests/ui/bad_explicit_impl.rs new file mode 100644 index 000000000..210644661 --- /dev/null +++ b/vendor/cxx/tests/ui/bad_explicit_impl.rs @@ -0,0 +1,10 @@ +#[cxx::bridge] +mod ffi { + struct S { + x: u8, + } + + impl fn() -> &S {} +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/bad_explicit_impl.stderr b/vendor/cxx/tests/ui/bad_explicit_impl.stderr new file mode 100644 index 000000000..c4748f421 --- /dev/null +++ b/vendor/cxx/tests/ui/bad_explicit_impl.stderr @@ -0,0 +1,5 @@ +error: unsupported Self type of explicit impl + --> tests/ui/bad_explicit_impl.rs:7:5 + | +7 | impl fn() -> &S {} + | ^^^^^^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/by_value_not_supported.rs b/vendor/cxx/tests/ui/by_value_not_supported.rs new file mode 100644 index 000000000..62bf8d4f3 --- /dev/null +++ b/vendor/cxx/tests/ui/by_value_not_supported.rs @@ -0,0 +1,22 @@ +#[cxx::bridge] +mod ffi { + struct S { + c: C, + r: R, + s: CxxString, + } + + extern "C++" { + type C; + } + + extern "Rust" { + type R; + + fn f(c: C) -> C; + fn g(r: R) -> R; + fn h(s: CxxString) -> CxxString; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/by_value_not_supported.stderr b/vendor/cxx/tests/ui/by_value_not_supported.stderr new file mode 100644 index 000000000..254c7bb45 --- /dev/null +++ b/vendor/cxx/tests/ui/by_value_not_supported.stderr @@ -0,0 +1,59 @@ +error: using opaque C++ type by value is not supported + --> tests/ui/by_value_not_supported.rs:4:9 + | +4 | c: C, + | ^^^^ + +error: using opaque Rust type by value is not supported + --> tests/ui/by_value_not_supported.rs:5:9 + | +5 | r: R, + | ^^^^ + +error: using C++ string by value is not supported + --> tests/ui/by_value_not_supported.rs:6:9 + | +6 | s: CxxString, + | ^^^^^^^^^^^^ + +error: needs a cxx::ExternType impl in order to be used as a field of `S`, argument of `f` or return value of `f` + --> tests/ui/by_value_not_supported.rs:10:9 + | +10 | type C; + | ^^^^^^ + +error: passing opaque C++ type by value is not supported + --> tests/ui/by_value_not_supported.rs:16:14 + | +16 | fn f(c: C) -> C; + | ^^^^ + +error: returning opaque C++ type by value is not supported + --> tests/ui/by_value_not_supported.rs:16:23 + | +16 | fn f(c: C) -> C; + | ^ + +error: passing opaque Rust type by value is not supported + --> tests/ui/by_value_not_supported.rs:17:14 + | +17 | fn g(r: R) -> R; + | ^^^^ + +error: returning opaque Rust type by value is not supported + --> tests/ui/by_value_not_supported.rs:17:23 + | +17 | fn g(r: R) -> R; + | ^ + +error: passing C++ string by value is not supported + --> tests/ui/by_value_not_supported.rs:18:14 + | +18 | fn h(s: CxxString) -> CxxString; + | ^^^^^^^^^^^^ + +error: returning C++ string by value is not supported + --> tests/ui/by_value_not_supported.rs:18:31 + | +18 | fn h(s: CxxString) -> CxxString; + | ^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/const_fn.rs b/vendor/cxx/tests/ui/const_fn.rs new file mode 100644 index 000000000..1ad489411 --- /dev/null +++ b/vendor/cxx/tests/ui/const_fn.rs @@ -0,0 +1,10 @@ +#[cxx::bridge] +mod ffi { + extern "Rust" { + const fn f(); + } +} + +const fn f() {} + +fn main() {} diff --git a/vendor/cxx/tests/ui/const_fn.stderr b/vendor/cxx/tests/ui/const_fn.stderr new file mode 100644 index 000000000..2dd6608af --- /dev/null +++ b/vendor/cxx/tests/ui/const_fn.stderr @@ -0,0 +1,5 @@ +error: const extern function is not supported + --> tests/ui/const_fn.rs:4:9 + | +4 | const fn f(); + | ^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/data_enums.rs b/vendor/cxx/tests/ui/data_enums.rs new file mode 100644 index 000000000..aa23200dc --- /dev/null +++ b/vendor/cxx/tests/ui/data_enums.rs @@ -0,0 +1,8 @@ +#[cxx::bridge] +mod ffi { + enum A { + Field(u64), + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/data_enums.stderr b/vendor/cxx/tests/ui/data_enums.stderr new file mode 100644 index 000000000..d8aa09e39 --- /dev/null +++ b/vendor/cxx/tests/ui/data_enums.stderr @@ -0,0 +1,5 @@ +error: enums with data are not supported yet + --> tests/ui/data_enums.rs:4:9 + | +4 | Field(u64), + | ^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/deny_elided_lifetimes.rs b/vendor/cxx/tests/ui/deny_elided_lifetimes.rs new file mode 100644 index 000000000..0ab3f750a --- /dev/null +++ b/vendor/cxx/tests/ui/deny_elided_lifetimes.rs @@ -0,0 +1,27 @@ +#![deny(elided_lifetimes_in_paths)] + +#[cxx::bridge] +mod ffi { + #[derive(PartialEq, PartialOrd, Hash)] + struct Struct<'a> { + reference: &'a i32, + } + + extern "Rust" { + type Rust<'a>; + } + + unsafe extern "C++" { + type Cpp<'a>; + + fn lifetime_named<'a>(s: &'a i32) -> UniquePtr<Cpp<'a>>; + + fn lifetime_underscore(s: &i32) -> UniquePtr<Cpp<'_>>; + + fn lifetime_elided(s: &i32) -> UniquePtr<Cpp>; + } +} + +pub struct Rust<'a>(&'a i32); + +fn main() {} diff --git a/vendor/cxx/tests/ui/deny_elided_lifetimes.stderr b/vendor/cxx/tests/ui/deny_elided_lifetimes.stderr new file mode 100644 index 000000000..857bb5b7f --- /dev/null +++ b/vendor/cxx/tests/ui/deny_elided_lifetimes.stderr @@ -0,0 +1,15 @@ +error: hidden lifetime parameters in types are deprecated + --> tests/ui/deny_elided_lifetimes.rs:21:50 + | +21 | fn lifetime_elided(s: &i32) -> UniquePtr<Cpp>; + | ^^^ expected lifetime parameter + | +note: the lint level is defined here + --> tests/ui/deny_elided_lifetimes.rs:1:9 + | +1 | #![deny(elided_lifetimes_in_paths)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: indicate the anonymous lifetime + | +21 | fn lifetime_elided(s: &i32) -> UniquePtr<Cpp<'_>>; + | ++++ diff --git a/vendor/cxx/tests/ui/deny_missing_docs.rs b/vendor/cxx/tests/ui/deny_missing_docs.rs new file mode 100644 index 000000000..037894bb8 --- /dev/null +++ b/vendor/cxx/tests/ui/deny_missing_docs.rs @@ -0,0 +1,94 @@ +// TODO: More work is needed so that the missing_docs lints produced by rustc +// are properly positioned inside of the bridge. + +//! ... + +#![deny(missing_docs)] + +/// ... +#[cxx::bridge] +pub mod ffi { + pub struct UndocumentedStruct { + pub undocumented_field: u8, + } + + /// ... + pub struct DocumentedStruct { + /// ... + pub documented_field: u8, + } + + pub enum UndocumentedEnum { + UndocumentedVariant = 0, + } + + /// ... + pub enum DocumentedEnum { + /// ... + DocumentedVariant = 0, + } + + extern "Rust" { + pub type UndocumentedRustType; + + /// ... + pub type DocumentedRustType; + + pub fn undocumented_rust_fn() -> u8; + + /// ... + pub fn documented_rust_fn() -> u8; + } + + unsafe extern "C++" { + pub type UndocumentedForeignType; + + /// ... + pub type DocumentedForeignType; + + pub type UndocumentedTypeAlias = crate::bindgen::UndocumentedTypeAlias; + + /// ... + pub type DocumentedTypeAlias = crate::bindgen::DocumentedTypeAlias; + + pub fn undocumented_foreign_fn() -> u8; + + /// ... + pub fn documented_foreign_fn() -> u8; + } + + #[allow(missing_docs)] + pub struct SuppressUndocumentedStruct { + pub undocumented_field: u8, + } +} + +struct UndocumentedRustType; +struct DocumentedRustType; + +mod bindgen { + use cxx::{type_id, ExternType}; + + pub struct UndocumentedTypeAlias; + pub struct DocumentedTypeAlias; + + unsafe impl ExternType for UndocumentedTypeAlias { + type Id = type_id!("UndocumentedTypeAlias"); + type Kind = cxx::kind::Opaque; + } + + unsafe impl ExternType for DocumentedTypeAlias { + type Id = type_id!("DocumentedTypeAlias"); + type Kind = cxx::kind::Opaque; + } +} + +fn undocumented_rust_fn() -> u8 { + 0 +} + +fn documented_rust_fn() -> u8 { + 0 +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/deny_missing_docs.stderr b/vendor/cxx/tests/ui/deny_missing_docs.stderr new file mode 100644 index 000000000..54ab987b4 --- /dev/null +++ b/vendor/cxx/tests/ui/deny_missing_docs.stderr @@ -0,0 +1,47 @@ +error: missing documentation for a struct + --> tests/ui/deny_missing_docs.rs:11:5 + | +11 | pub struct UndocumentedStruct { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui/deny_missing_docs.rs:6:9 + | +6 | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a struct field + --> tests/ui/deny_missing_docs.rs:12:9 + | +12 | pub undocumented_field: u8, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a struct + --> tests/ui/deny_missing_docs.rs:21:5 + | +21 | pub enum UndocumentedEnum { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for an associated constant + --> tests/ui/deny_missing_docs.rs:22:9 + | +22 | UndocumentedVariant = 0, + | ^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a struct + --> tests/ui/deny_missing_docs.rs:44:9 + | +44 | pub type UndocumentedForeignType; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a type alias + --> tests/ui/deny_missing_docs.rs:49:9 + | +49 | pub type UndocumentedTypeAlias = crate::bindgen::UndocumentedTypeAlias; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for a function + --> tests/ui/deny_missing_docs.rs:54:9 + | +54 | pub fn undocumented_foreign_fn() -> u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/derive_duplicate.rs b/vendor/cxx/tests/ui/derive_duplicate.rs new file mode 100644 index 000000000..3061f765c --- /dev/null +++ b/vendor/cxx/tests/ui/derive_duplicate.rs @@ -0,0 +1,9 @@ +#[cxx::bridge] +mod ffi { + #[derive(Clone, Clone)] + struct Struct { + x: usize, + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/derive_duplicate.stderr b/vendor/cxx/tests/ui/derive_duplicate.stderr new file mode 100644 index 000000000..759208629 --- /dev/null +++ b/vendor/cxx/tests/ui/derive_duplicate.stderr @@ -0,0 +1,7 @@ +error[E0119]: conflicting implementations of trait `Clone` for type `Struct` + --> tests/ui/derive_duplicate.rs:3:21 + | +3 | #[derive(Clone, Clone)] + | ----- ^^^^^ conflicting implementation for `Struct` + | | + | first implementation here diff --git a/vendor/cxx/tests/ui/derive_noncopy.rs b/vendor/cxx/tests/ui/derive_noncopy.rs new file mode 100644 index 000000000..ae705fd00 --- /dev/null +++ b/vendor/cxx/tests/ui/derive_noncopy.rs @@ -0,0 +1,13 @@ +#[cxx::bridge] +mod ffi { + #[derive(Copy)] + struct TryCopy { + other: Other, + } + + struct Other { + x: usize, + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/derive_noncopy.stderr b/vendor/cxx/tests/ui/derive_noncopy.stderr new file mode 100644 index 000000000..b4f35d3e4 --- /dev/null +++ b/vendor/cxx/tests/ui/derive_noncopy.stderr @@ -0,0 +1,7 @@ +error[E0204]: the trait `Copy` cannot be implemented for this type + --> tests/ui/derive_noncopy.rs:4:12 + | +4 | struct TryCopy { + | ^^^^^^^ +5 | other: Other, + | ------------ this field does not implement `Copy` diff --git a/vendor/cxx/tests/ui/drop_shared.rs b/vendor/cxx/tests/ui/drop_shared.rs new file mode 100644 index 000000000..5e3de4a1e --- /dev/null +++ b/vendor/cxx/tests/ui/drop_shared.rs @@ -0,0 +1,14 @@ +#[cxx::bridge] +mod ffi { + struct Shared { + fd: i32, + } +} + +impl Drop for ffi::Shared { + fn drop(&mut self) { + println!("close({})", self.fd); + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/drop_shared.stderr b/vendor/cxx/tests/ui/drop_shared.stderr new file mode 100644 index 000000000..41a5287f7 --- /dev/null +++ b/vendor/cxx/tests/ui/drop_shared.stderr @@ -0,0 +1,8 @@ +error[E0119]: conflicting implementations of trait `forbid::Drop` for type `Shared` + --> tests/ui/drop_shared.rs:3:5 + | +1 | #[cxx::bridge] + | -------------- first implementation here +2 | mod ffi { +3 | struct Shared { + | ^^^^^^^^^^^^^ conflicting implementation for `Shared` diff --git a/vendor/cxx/tests/ui/empty_enum.rs b/vendor/cxx/tests/ui/empty_enum.rs new file mode 100644 index 000000000..987004bb3 --- /dev/null +++ b/vendor/cxx/tests/ui/empty_enum.rs @@ -0,0 +1,6 @@ +#[cxx::bridge] +mod ffi { + enum A {} +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/empty_enum.stderr b/vendor/cxx/tests/ui/empty_enum.stderr new file mode 100644 index 000000000..60d3b5da3 --- /dev/null +++ b/vendor/cxx/tests/ui/empty_enum.stderr @@ -0,0 +1,5 @@ +error: explicit #[repr(...)] is required for enum without any variants + --> tests/ui/empty_enum.rs:3:5 + | +3 | enum A {} + | ^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/empty_struct.rs b/vendor/cxx/tests/ui/empty_struct.rs new file mode 100644 index 000000000..060cfe0fa --- /dev/null +++ b/vendor/cxx/tests/ui/empty_struct.rs @@ -0,0 +1,6 @@ +#[cxx::bridge] +mod ffi { + struct Empty {} +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/empty_struct.stderr b/vendor/cxx/tests/ui/empty_struct.stderr new file mode 100644 index 000000000..f6fbfc117 --- /dev/null +++ b/vendor/cxx/tests/ui/empty_struct.stderr @@ -0,0 +1,5 @@ +error: structs without any fields are not supported + --> tests/ui/empty_struct.rs:3:5 + | +3 | struct Empty {} + | ^^^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/enum_inconsistent.rs b/vendor/cxx/tests/ui/enum_inconsistent.rs new file mode 100644 index 000000000..cd5ffa5b9 --- /dev/null +++ b/vendor/cxx/tests/ui/enum_inconsistent.rs @@ -0,0 +1,9 @@ +#[cxx::bridge] +mod ffi { + enum Bad { + A = 1u16, + B = 2i64, + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/enum_inconsistent.stderr b/vendor/cxx/tests/ui/enum_inconsistent.stderr new file mode 100644 index 000000000..d6d7837e1 --- /dev/null +++ b/vendor/cxx/tests/ui/enum_inconsistent.stderr @@ -0,0 +1,5 @@ +error: expected u16, found i64 + --> tests/ui/enum_inconsistent.rs:5:9 + | +5 | B = 2i64, + | ^^^^^^^^ diff --git a/vendor/cxx/tests/ui/enum_match_without_wildcard.rs b/vendor/cxx/tests/ui/enum_match_without_wildcard.rs new file mode 100644 index 000000000..1a119429b --- /dev/null +++ b/vendor/cxx/tests/ui/enum_match_without_wildcard.rs @@ -0,0 +1,16 @@ +#[cxx::bridge] +mod ffi { + enum A { + FieldA, + FieldB, + } +} + +fn main() {} + +fn matcher(a: ffi::A) -> u32 { + match a { + ffi::A::FieldA => 2020, + ffi::A::FieldB => 2021, + } +} diff --git a/vendor/cxx/tests/ui/enum_match_without_wildcard.stderr b/vendor/cxx/tests/ui/enum_match_without_wildcard.stderr new file mode 100644 index 000000000..5808d6f8f --- /dev/null +++ b/vendor/cxx/tests/ui/enum_match_without_wildcard.stderr @@ -0,0 +1,17 @@ +error[E0004]: non-exhaustive patterns: `ffi::A { repr: 2_u8..=u8::MAX }` not covered + --> tests/ui/enum_match_without_wildcard.rs:12:11 + | +12 | match a { + | ^ pattern `ffi::A { repr: 2_u8..=u8::MAX }` not covered + | +note: `ffi::A` defined here + --> tests/ui/enum_match_without_wildcard.rs:3:10 + | +3 | enum A { + | ^ + = note: the matched value is of type `ffi::A` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +14 ~ ffi::A::FieldB => 2021, +15 ~ ffi::A { repr: 2_u8..=u8::MAX } => todo!(), + | diff --git a/vendor/cxx/tests/ui/enum_out_of_bounds.rs b/vendor/cxx/tests/ui/enum_out_of_bounds.rs new file mode 100644 index 000000000..9e0090b08 --- /dev/null +++ b/vendor/cxx/tests/ui/enum_out_of_bounds.rs @@ -0,0 +1,13 @@ +#[cxx::bridge] +mod ffi { + #[repr(u32)] + enum Bad1 { + A = 0xFFFF_FFFF_FFFF_FFFF, + } + enum Bad2 { + A = 2000, + B = 1u8, + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/enum_out_of_bounds.stderr b/vendor/cxx/tests/ui/enum_out_of_bounds.stderr new file mode 100644 index 000000000..3244b6a7b --- /dev/null +++ b/vendor/cxx/tests/ui/enum_out_of_bounds.stderr @@ -0,0 +1,11 @@ +error: discriminant value `18446744073709551615` is outside the limits of u32 + --> tests/ui/enum_out_of_bounds.rs:5:9 + | +5 | A = 0xFFFF_FFFF_FFFF_FFFF, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: discriminant value `2000` is outside the limits of u8 + --> tests/ui/enum_out_of_bounds.rs:9:9 + | +9 | B = 1u8, + | ^^^^^^^ diff --git a/vendor/cxx/tests/ui/enum_overflows.rs b/vendor/cxx/tests/ui/enum_overflows.rs new file mode 100644 index 000000000..29de1a008 --- /dev/null +++ b/vendor/cxx/tests/ui/enum_overflows.rs @@ -0,0 +1,17 @@ +#[cxx::bridge] +mod ffi { + enum Good1 { + A = 0xFFFF_FFFF_FFFF_FFFF, + } + enum Good2 { + B = 0xFFFF_FFFF_FFFF_FFFF, + C = 2020, + } + enum Bad { + D = 0xFFFF_FFFF_FFFF_FFFE, + E, + F, + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/enum_overflows.stderr b/vendor/cxx/tests/ui/enum_overflows.stderr new file mode 100644 index 000000000..76c37bb03 --- /dev/null +++ b/vendor/cxx/tests/ui/enum_overflows.stderr @@ -0,0 +1,5 @@ +error: discriminant overflow on value after 18446744073709551615 + --> tests/ui/enum_overflows.rs:13:9 + | +13 | F, + | ^ diff --git a/vendor/cxx/tests/ui/enum_receiver.rs b/vendor/cxx/tests/ui/enum_receiver.rs new file mode 100644 index 000000000..a27f27468 --- /dev/null +++ b/vendor/cxx/tests/ui/enum_receiver.rs @@ -0,0 +1,11 @@ +#[cxx::bridge] +mod ffi { + enum Enum { + Variant, + } + extern "Rust" { + fn f(self: &Enum); + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/enum_receiver.stderr b/vendor/cxx/tests/ui/enum_receiver.stderr new file mode 100644 index 000000000..ace767760 --- /dev/null +++ b/vendor/cxx/tests/ui/enum_receiver.stderr @@ -0,0 +1,5 @@ +error: unsupported receiver type; C++ does not allow member functions on enums + --> tests/ui/enum_receiver.rs:7:20 + | +7 | fn f(self: &Enum); + | ^^^^^ diff --git a/vendor/cxx/tests/ui/enum_unsatisfiable.rs b/vendor/cxx/tests/ui/enum_unsatisfiable.rs new file mode 100644 index 000000000..619128743 --- /dev/null +++ b/vendor/cxx/tests/ui/enum_unsatisfiable.rs @@ -0,0 +1,9 @@ +#[cxx::bridge] +mod ffi { + enum Bad { + A = -0xFFFF_FFFF_FFFF_FFFF, + B = 0xFFFF_FFFF_FFFF_FFFF, + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/enum_unsatisfiable.stderr b/vendor/cxx/tests/ui/enum_unsatisfiable.stderr new file mode 100644 index 000000000..e2b37bdd0 --- /dev/null +++ b/vendor/cxx/tests/ui/enum_unsatisfiable.stderr @@ -0,0 +1,8 @@ +error: these discriminant values do not fit in any supported enum repr type + --> tests/ui/enum_unsatisfiable.rs:3:5 + | +3 | / enum Bad { +4 | | A = -0xFFFF_FFFF_FFFF_FFFF, +5 | | B = 0xFFFF_FFFF_FFFF_FFFF, +6 | | } + | |_____^ diff --git a/vendor/cxx/tests/ui/expected_named.rs b/vendor/cxx/tests/ui/expected_named.rs new file mode 100644 index 000000000..31626d1f6 --- /dev/null +++ b/vendor/cxx/tests/ui/expected_named.rs @@ -0,0 +1,9 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + type Borrowed<'a>; + fn borrowed() -> UniquePtr<Borrowed>; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/expected_named.stderr b/vendor/cxx/tests/ui/expected_named.stderr new file mode 100644 index 000000000..0068bdf36 --- /dev/null +++ b/vendor/cxx/tests/ui/expected_named.stderr @@ -0,0 +1,11 @@ +error[E0106]: missing lifetime specifier + --> tests/ui/expected_named.rs:5:36 + | +5 | fn borrowed() -> UniquePtr<Borrowed>; + | ^^^^^^^^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from +help: consider using the `'static` lifetime + | +5 | fn borrowed() -> UniquePtr<Borrowed<'static>>; + | +++++++++ diff --git a/vendor/cxx/tests/ui/extern_fn_abi.rs b/vendor/cxx/tests/ui/extern_fn_abi.rs new file mode 100644 index 000000000..1f9333885 --- /dev/null +++ b/vendor/cxx/tests/ui/extern_fn_abi.rs @@ -0,0 +1,8 @@ +#[cxx::bridge] +mod ffi { + extern "C++" { + extern "Java" fn f(); + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/extern_fn_abi.stderr b/vendor/cxx/tests/ui/extern_fn_abi.stderr new file mode 100644 index 000000000..32ef9c3e0 --- /dev/null +++ b/vendor/cxx/tests/ui/extern_fn_abi.stderr @@ -0,0 +1,5 @@ +error: explicit ABI on extern function is not supported + --> tests/ui/extern_fn_abi.rs:4:9 + | +4 | extern "Java" fn f(); + | ^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/extern_type_bound.rs b/vendor/cxx/tests/ui/extern_type_bound.rs new file mode 100644 index 000000000..958accd38 --- /dev/null +++ b/vendor/cxx/tests/ui/extern_type_bound.rs @@ -0,0 +1,15 @@ +#[cxx::bridge] +mod ffi { + extern "C++" { + type Opaque: PartialEq + PartialOrd; + } +} + +#[cxx::bridge] +mod ffi { + extern "C++" { + type Opaque: for<'de> Deserialize<'de>; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/extern_type_bound.stderr b/vendor/cxx/tests/ui/extern_type_bound.stderr new file mode 100644 index 000000000..1d6796bc6 --- /dev/null +++ b/vendor/cxx/tests/ui/extern_type_bound.stderr @@ -0,0 +1,11 @@ +error: extern type bounds are not implemented yet + --> tests/ui/extern_type_bound.rs:4:22 + | +4 | type Opaque: PartialEq + PartialOrd; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unsupported trait + --> tests/ui/extern_type_bound.rs:11:22 + | +11 | type Opaque: for<'de> Deserialize<'de>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/extern_type_generic.rs b/vendor/cxx/tests/ui/extern_type_generic.rs new file mode 100644 index 000000000..4de2c981f --- /dev/null +++ b/vendor/cxx/tests/ui/extern_type_generic.rs @@ -0,0 +1,8 @@ +#[cxx::bridge] +mod ffi { + extern "C++" { + type Generic<T>; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/extern_type_generic.stderr b/vendor/cxx/tests/ui/extern_type_generic.stderr new file mode 100644 index 000000000..2b312f0e0 --- /dev/null +++ b/vendor/cxx/tests/ui/extern_type_generic.stderr @@ -0,0 +1,5 @@ +error: extern type with generic type parameter is not supported yet + --> tests/ui/extern_type_generic.rs:4:22 + | +4 | type Generic<T>; + | ^ diff --git a/vendor/cxx/tests/ui/extern_type_lifetime_bound.rs b/vendor/cxx/tests/ui/extern_type_lifetime_bound.rs new file mode 100644 index 000000000..ad581818b --- /dev/null +++ b/vendor/cxx/tests/ui/extern_type_lifetime_bound.rs @@ -0,0 +1,8 @@ +#[cxx::bridge] +mod ffi { + extern "C++" { + type Complex<'a, 'b: 'a>; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/extern_type_lifetime_bound.stderr b/vendor/cxx/tests/ui/extern_type_lifetime_bound.stderr new file mode 100644 index 000000000..6c3fc7f19 --- /dev/null +++ b/vendor/cxx/tests/ui/extern_type_lifetime_bound.stderr @@ -0,0 +1,5 @@ +error: lifetime parameter with bounds is not supported yet + --> tests/ui/extern_type_lifetime_bound.rs:4:26 + | +4 | type Complex<'a, 'b: 'a>; + | ^^^^^^ diff --git a/vendor/cxx/tests/ui/fallible_fnptr.rs b/vendor/cxx/tests/ui/fallible_fnptr.rs new file mode 100644 index 000000000..c45813de5 --- /dev/null +++ b/vendor/cxx/tests/ui/fallible_fnptr.rs @@ -0,0 +1,8 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + fn f(callback: fn() -> Result<()>); + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/fallible_fnptr.stderr b/vendor/cxx/tests/ui/fallible_fnptr.stderr new file mode 100644 index 000000000..4635ec8f7 --- /dev/null +++ b/vendor/cxx/tests/ui/fallible_fnptr.stderr @@ -0,0 +1,5 @@ +error: function pointer returning Result is not supported yet + --> tests/ui/fallible_fnptr.rs:4:24 + | +4 | fn f(callback: fn() -> Result<()>); + | ^^^^^^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/function_with_body.rs b/vendor/cxx/tests/ui/function_with_body.rs new file mode 100644 index 000000000..52be79af0 --- /dev/null +++ b/vendor/cxx/tests/ui/function_with_body.rs @@ -0,0 +1,8 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + fn f() {} + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/function_with_body.stderr b/vendor/cxx/tests/ui/function_with_body.stderr new file mode 100644 index 000000000..f2078df4d --- /dev/null +++ b/vendor/cxx/tests/ui/function_with_body.stderr @@ -0,0 +1,5 @@ +error: expected `;` + --> tests/ui/function_with_body.rs:4:16 + | +4 | fn f() {} + | ^ diff --git a/vendor/cxx/tests/ui/generic_enum.rs b/vendor/cxx/tests/ui/generic_enum.rs new file mode 100644 index 000000000..feeb94be6 --- /dev/null +++ b/vendor/cxx/tests/ui/generic_enum.rs @@ -0,0 +1,16 @@ +#[cxx::bridge] +mod ffi { + enum A<T> { + Field, + } + + enum B<T> where T: Copy { + Field, + } + + enum C where void: Copy { + Field, + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/generic_enum.stderr b/vendor/cxx/tests/ui/generic_enum.stderr new file mode 100644 index 000000000..2529af733 --- /dev/null +++ b/vendor/cxx/tests/ui/generic_enum.stderr @@ -0,0 +1,17 @@ +error: enum with generic parameters is not supported + --> tests/ui/generic_enum.rs:3:5 + | +3 | enum A<T> { + | ^^^^^^^^^ + +error: enum with generic parameters is not supported + --> tests/ui/generic_enum.rs:7:5 + | +7 | enum B<T> where T: Copy { + | ^^^^^^^^^ + +error: enum with where-clause is not supported + --> tests/ui/generic_enum.rs:11:12 + | +11 | enum C where void: Copy { + | ^^^^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/impl_trait_for_type.rs b/vendor/cxx/tests/ui/impl_trait_for_type.rs new file mode 100644 index 000000000..9284f738b --- /dev/null +++ b/vendor/cxx/tests/ui/impl_trait_for_type.rs @@ -0,0 +1,10 @@ +#[cxx::bridge] +mod ffi { + struct S { + x: u8, + } + + impl UniquePtrTarget for S {} +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/impl_trait_for_type.stderr b/vendor/cxx/tests/ui/impl_trait_for_type.stderr new file mode 100644 index 000000000..fa99de5a9 --- /dev/null +++ b/vendor/cxx/tests/ui/impl_trait_for_type.stderr @@ -0,0 +1,5 @@ +error: unexpected impl, expected something like `impl UniquePtr<T> {}` + --> tests/ui/impl_trait_for_type.rs:7:10 + | +7 | impl UniquePtrTarget for S {} + | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/include.rs b/vendor/cxx/tests/ui/include.rs new file mode 100644 index 000000000..3e848b581 --- /dev/null +++ b/vendor/cxx/tests/ui/include.rs @@ -0,0 +1,12 @@ +#[cxx::bridge] +mod ffi { + extern "C++" { + include!("path/to" what); + include!(<path/to> what); + include!(<path/to); + include!(<path[to]>); + include!(...); + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/include.stderr b/vendor/cxx/tests/ui/include.stderr new file mode 100644 index 000000000..b801530e1 --- /dev/null +++ b/vendor/cxx/tests/ui/include.stderr @@ -0,0 +1,29 @@ +error: unexpected token + --> tests/ui/include.rs:4:28 + | +4 | include!("path/to" what); + | ^^^^ + +error: unexpected token + --> tests/ui/include.rs:5:28 + | +5 | include!(<path/to> what); + | ^^^^ + +error: expected `>` + --> tests/ui/include.rs:6:26 + | +6 | include!(<path/to); + | ^ + +error: unexpected token in include path + --> tests/ui/include.rs:7:23 + | +7 | include!(<path[to]>); + | ^^^^ + +error: expected "quoted/path/to" or <bracketed/path/to> + --> tests/ui/include.rs:8:18 + | +8 | include!(...); + | ^ diff --git a/vendor/cxx/tests/ui/lifetime_extern_cxx.rs b/vendor/cxx/tests/ui/lifetime_extern_cxx.rs new file mode 100644 index 000000000..e85b3392e --- /dev/null +++ b/vendor/cxx/tests/ui/lifetime_extern_cxx.rs @@ -0,0 +1,9 @@ +#[cxx::bridge] +mod ffi { + extern "C++" { + type Opaque; + unsafe fn f<'a>(&'a self, arg: &str) -> &'a str; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/lifetime_extern_cxx.stderr b/vendor/cxx/tests/ui/lifetime_extern_cxx.stderr new file mode 100644 index 000000000..a5cc3bdaa --- /dev/null +++ b/vendor/cxx/tests/ui/lifetime_extern_cxx.stderr @@ -0,0 +1,5 @@ +error: extern C++ function with lifetimes must be declared in `unsafe extern "C++"` block + --> tests/ui/lifetime_extern_cxx.rs:5:9 + | +5 | unsafe fn f<'a>(&'a self, arg: &str) -> &'a str; + | ^^^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/lifetime_extern_rust.rs b/vendor/cxx/tests/ui/lifetime_extern_rust.rs new file mode 100644 index 000000000..72c37cba7 --- /dev/null +++ b/vendor/cxx/tests/ui/lifetime_extern_rust.rs @@ -0,0 +1,17 @@ +#[cxx::bridge] +mod ffi { + extern "Rust" { + type Opaque; + fn f<'a>(&'a self, arg: &str) -> &'a str; + } +} + +pub struct Opaque; + +impl Opaque { + fn f(&self, _arg: &str) -> &str { + "" + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/lifetime_extern_rust.stderr b/vendor/cxx/tests/ui/lifetime_extern_rust.stderr new file mode 100644 index 000000000..b2ca4950b --- /dev/null +++ b/vendor/cxx/tests/ui/lifetime_extern_rust.stderr @@ -0,0 +1,5 @@ +error: must be `unsafe fn f` in order to expose explicit lifetimes to C++ + --> tests/ui/lifetime_extern_rust.rs:5:9 + | +5 | fn f<'a>(&'a self, arg: &str) -> &'a str; + | ^^^^^^^^ diff --git a/vendor/cxx/tests/ui/missing_unsafe.rs b/vendor/cxx/tests/ui/missing_unsafe.rs new file mode 100644 index 000000000..d8c0a23a2 --- /dev/null +++ b/vendor/cxx/tests/ui/missing_unsafe.rs @@ -0,0 +1,10 @@ +#[cxx::bridge] +mod ffi { + extern "Rust" { + fn f(x: i32); + } +} + +unsafe fn f(_x: i32) {} + +fn main() {} diff --git a/vendor/cxx/tests/ui/missing_unsafe.stderr b/vendor/cxx/tests/ui/missing_unsafe.stderr new file mode 100644 index 000000000..e7dcba749 --- /dev/null +++ b/vendor/cxx/tests/ui/missing_unsafe.stderr @@ -0,0 +1,9 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> tests/ui/missing_unsafe.rs:4:12 + | +4 | fn f(x: i32); + | ^ - items do not inherit unsafety from separate enclosing items + | | + | call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior diff --git a/vendor/cxx/tests/ui/multiple_parse_error.rs b/vendor/cxx/tests/ui/multiple_parse_error.rs new file mode 100644 index 000000000..138d6d6c2 --- /dev/null +++ b/vendor/cxx/tests/ui/multiple_parse_error.rs @@ -0,0 +1,8 @@ +#[cxx::bridge] +mod ffi { + struct Monad<T>; + + extern "Haskell" {} +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/multiple_parse_error.stderr b/vendor/cxx/tests/ui/multiple_parse_error.stderr new file mode 100644 index 000000000..32b8e5601 --- /dev/null +++ b/vendor/cxx/tests/ui/multiple_parse_error.stderr @@ -0,0 +1,11 @@ +error: unit structs are not supported + --> tests/ui/multiple_parse_error.rs:3:5 + | +3 | struct Monad<T>; + | ^^^^^^^^^^^^^^^^ + +error: unrecognized ABI, requires either "C++" or "Rust" + --> tests/ui/multiple_parse_error.rs:5:5 + | +5 | extern "Haskell" {} + | ^^^^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/mut_return.rs b/vendor/cxx/tests/ui/mut_return.rs new file mode 100644 index 000000000..f30988b8c --- /dev/null +++ b/vendor/cxx/tests/ui/mut_return.rs @@ -0,0 +1,18 @@ +#[cxx::bridge] +mod ffi { + extern "Rust" { + type Mut<'a>; + } + + unsafe extern "C++" { + type Thing; + + fn f(t: &Thing) -> Pin<&mut CxxString>; + unsafe fn g(t: &Thing) -> Pin<&mut CxxString>; + fn h(t: Box<Mut>) -> Pin<&mut CxxString>; + fn i<'a>(t: Box<Mut<'a>>) -> Pin<&'a mut CxxString>; + fn j(t: &Thing) -> &mut [u8]; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/mut_return.stderr b/vendor/cxx/tests/ui/mut_return.stderr new file mode 100644 index 000000000..37e947a79 --- /dev/null +++ b/vendor/cxx/tests/ui/mut_return.stderr @@ -0,0 +1,11 @@ +error: &mut return type is not allowed unless there is a &mut argument + --> tests/ui/mut_return.rs:10:9 + | +10 | fn f(t: &Thing) -> Pin<&mut CxxString>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: &mut return type is not allowed unless there is a &mut argument + --> tests/ui/mut_return.rs:14:9 + | +14 | fn j(t: &Thing) -> &mut [u8]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/non_integer_discriminant_enum.rs b/vendor/cxx/tests/ui/non_integer_discriminant_enum.rs new file mode 100644 index 000000000..388b46398 --- /dev/null +++ b/vendor/cxx/tests/ui/non_integer_discriminant_enum.rs @@ -0,0 +1,8 @@ +#[cxx::bridge] +mod ffi { + enum A { + Field = 2020 + 1, + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/non_integer_discriminant_enum.stderr b/vendor/cxx/tests/ui/non_integer_discriminant_enum.stderr new file mode 100644 index 000000000..aa4388fb9 --- /dev/null +++ b/vendor/cxx/tests/ui/non_integer_discriminant_enum.stderr @@ -0,0 +1,5 @@ +error: enums with non-integer literal discriminants are not supported yet + --> tests/ui/non_integer_discriminant_enum.rs:4:9 + | +4 | Field = 2020 + 1, + | ^^^^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/nonempty_impl_block.rs b/vendor/cxx/tests/ui/nonempty_impl_block.rs new file mode 100644 index 000000000..239d1ece6 --- /dev/null +++ b/vendor/cxx/tests/ui/nonempty_impl_block.rs @@ -0,0 +1,12 @@ +#[cxx::bridge] +mod ffi { + struct S { + x: u8, + } + + impl UniquePtr<S> { + fn new() -> Self; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/nonempty_impl_block.stderr b/vendor/cxx/tests/ui/nonempty_impl_block.stderr new file mode 100644 index 000000000..6f6983053 --- /dev/null +++ b/vendor/cxx/tests/ui/nonempty_impl_block.stderr @@ -0,0 +1,8 @@ +error: expected an empty impl block + --> tests/ui/nonempty_impl_block.rs:7:23 + | +7 | impl UniquePtr<S> { + | _______________________^ +8 | | fn new() -> Self; +9 | | } + | |_____^ diff --git a/vendor/cxx/tests/ui/nonlocal_rust_type.rs b/vendor/cxx/tests/ui/nonlocal_rust_type.rs new file mode 100644 index 000000000..d8a238aee --- /dev/null +++ b/vendor/cxx/tests/ui/nonlocal_rust_type.rs @@ -0,0 +1,18 @@ +pub struct MyBuilder<'a> { + _s: &'a str, +} + +type OptBuilder<'a> = Option<MyBuilder<'a>>; + +#[cxx::bridge] +mod ffi { + extern "Rust" { + type OptBuilder<'a>; + } + + struct MyBuilder<'a> { + rs: Box<OptBuilder<'a>>, + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/nonlocal_rust_type.stderr b/vendor/cxx/tests/ui/nonlocal_rust_type.stderr new file mode 100644 index 000000000..f6cb06cb6 --- /dev/null +++ b/vendor/cxx/tests/ui/nonlocal_rust_type.stderr @@ -0,0 +1,21 @@ +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> tests/ui/nonlocal_rust_type.rs:10:9 + | +10 | type OptBuilder<'a>; + | ^^^^^-------------- + | | | + | | `Option` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate + --> tests/ui/nonlocal_rust_type.rs:14:13 + | +14 | rs: Box<OptBuilder<'a>>, + | ^^^^-------------- + | | | + | | `Option` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead diff --git a/vendor/cxx/tests/ui/opaque_autotraits.rs b/vendor/cxx/tests/ui/opaque_autotraits.rs new file mode 100644 index 000000000..99406d74e --- /dev/null +++ b/vendor/cxx/tests/ui/opaque_autotraits.rs @@ -0,0 +1,16 @@ +#[cxx::bridge] +mod ffi { + extern "C++" { + type Opaque; + } +} + +fn assert_send<T: Send>() {} +fn assert_sync<T: Sync>() {} +fn assert_unpin<T: Unpin>() {} + +fn main() { + assert_send::<ffi::Opaque>(); + assert_sync::<ffi::Opaque>(); + assert_unpin::<ffi::Opaque>(); +} diff --git a/vendor/cxx/tests/ui/opaque_autotraits.stderr b/vendor/cxx/tests/ui/opaque_autotraits.stderr new file mode 100644 index 000000000..c6447c558 --- /dev/null +++ b/vendor/cxx/tests/ui/opaque_autotraits.stderr @@ -0,0 +1,59 @@ +error[E0277]: `*const cxx::void` cannot be sent between threads safely + --> tests/ui/opaque_autotraits.rs:13:19 + | +13 | assert_send::<ffi::Opaque>(); + | ^^^^^^^^^^^ `*const cxx::void` cannot be sent between threads safely + | + = help: within `ffi::Opaque`, the trait `Send` is not implemented for `*const cxx::void` + = note: required because it appears within the type `[*const void; 0]` + = note: required because it appears within the type `Opaque` +note: required because it appears within the type `Opaque` + --> tests/ui/opaque_autotraits.rs:4:14 + | +4 | type Opaque; + | ^^^^^^ +note: required by a bound in `assert_send` + --> tests/ui/opaque_autotraits.rs:8:19 + | +8 | fn assert_send<T: Send>() {} + | ^^^^ required by this bound in `assert_send` + +error[E0277]: `*const cxx::void` cannot be shared between threads safely + --> tests/ui/opaque_autotraits.rs:14:19 + | +14 | assert_sync::<ffi::Opaque>(); + | ^^^^^^^^^^^ `*const cxx::void` cannot be shared between threads safely + | + = help: within `ffi::Opaque`, the trait `Sync` is not implemented for `*const cxx::void` + = note: required because it appears within the type `[*const void; 0]` + = note: required because it appears within the type `Opaque` +note: required because it appears within the type `Opaque` + --> tests/ui/opaque_autotraits.rs:4:14 + | +4 | type Opaque; + | ^^^^^^ +note: required by a bound in `assert_sync` + --> tests/ui/opaque_autotraits.rs:9:19 + | +9 | fn assert_sync<T: Sync>() {} + | ^^^^ required by this bound in `assert_sync` + +error[E0277]: `PhantomPinned` cannot be unpinned + --> tests/ui/opaque_autotraits.rs:15:20 + | +15 | assert_unpin::<ffi::Opaque>(); + | ^^^^^^^^^^^ within `ffi::Opaque`, the trait `Unpin` is not implemented for `PhantomPinned` + | + = note: consider using `Box::pin` + = note: required because it appears within the type `PhantomData<PhantomPinned>` + = note: required because it appears within the type `Opaque` +note: required because it appears within the type `Opaque` + --> tests/ui/opaque_autotraits.rs:4:14 + | +4 | type Opaque; + | ^^^^^^ +note: required by a bound in `assert_unpin` + --> tests/ui/opaque_autotraits.rs:10:20 + | +10 | fn assert_unpin<T: Unpin>() {} + | ^^^^^ required by this bound in `assert_unpin` diff --git a/vendor/cxx/tests/ui/opaque_not_sized.rs b/vendor/cxx/tests/ui/opaque_not_sized.rs new file mode 100644 index 000000000..754e8d36c --- /dev/null +++ b/vendor/cxx/tests/ui/opaque_not_sized.rs @@ -0,0 +1,10 @@ +#[cxx::bridge] +mod ffi { + extern "Rust" { + type TypeR; + } +} + +struct TypeR(str); + +fn main() {} diff --git a/vendor/cxx/tests/ui/opaque_not_sized.stderr b/vendor/cxx/tests/ui/opaque_not_sized.stderr new file mode 100644 index 000000000..85be4af3b --- /dev/null +++ b/vendor/cxx/tests/ui/opaque_not_sized.stderr @@ -0,0 +1,17 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> tests/ui/opaque_not_sized.rs:4:14 + | +4 | type TypeR; + | ^^^^^ doesn't have a size known at compile-time + | + = help: within `TypeR`, the trait `Sized` is not implemented for `str` +note: required because it appears within the type `TypeR` + --> tests/ui/opaque_not_sized.rs:8:8 + | +8 | struct TypeR(str); + | ^^^^^ +note: required by a bound in `__AssertSized` + --> tests/ui/opaque_not_sized.rs:4:9 + | +4 | type TypeR; + | ^^^^^^^^^^^ required by this bound in `__AssertSized` diff --git a/vendor/cxx/tests/ui/pin_mut_opaque.rs b/vendor/cxx/tests/ui/pin_mut_opaque.rs new file mode 100644 index 000000000..ac1ca43af --- /dev/null +++ b/vendor/cxx/tests/ui/pin_mut_opaque.rs @@ -0,0 +1,14 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + type Opaque; + fn f(arg: &mut Opaque); + fn g(&mut self); + fn h(self: &mut Opaque); + fn s(s: &mut CxxString); + fn v(v: &mut CxxVector<u8>); + } + +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/pin_mut_opaque.stderr b/vendor/cxx/tests/ui/pin_mut_opaque.stderr new file mode 100644 index 000000000..8a5e019b3 --- /dev/null +++ b/vendor/cxx/tests/ui/pin_mut_opaque.stderr @@ -0,0 +1,35 @@ +error: mutable reference to C++ type requires a pin -- use Pin<&mut Opaque> + --> tests/ui/pin_mut_opaque.rs:5:19 + | +5 | fn f(arg: &mut Opaque); + | ^^^^^^^^^^^ + +error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxString> + --> tests/ui/pin_mut_opaque.rs:8:17 + | +8 | fn s(s: &mut CxxString); + | ^^^^^^^^^^^^^^ + +error: mutable reference to C++ type requires a pin -- use Pin<&mut CxxVector<...>> + --> tests/ui/pin_mut_opaque.rs:9:17 + | +9 | fn v(v: &mut CxxVector<u8>); + | ^^^^^^^^^^^^^^^^^^ + +error: needs a cxx::ExternType impl in order to be used as a non-pinned mutable reference in signature of `f`, `g`, `h` + --> tests/ui/pin_mut_opaque.rs:4:9 + | +4 | type Opaque; + | ^^^^^^^^^^^ + +error: mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut Opaque>` + --> tests/ui/pin_mut_opaque.rs:6:14 + | +6 | fn g(&mut self); + | ^^^^^^^^^ + +error: mutable reference to opaque C++ type requires a pin -- use `self: Pin<&mut Opaque>` + --> tests/ui/pin_mut_opaque.rs:7:20 + | +7 | fn h(self: &mut Opaque); + | ^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/ptr_in_fnptr.rs b/vendor/cxx/tests/ui/ptr_in_fnptr.rs new file mode 100644 index 000000000..73c97c666 --- /dev/null +++ b/vendor/cxx/tests/ui/ptr_in_fnptr.rs @@ -0,0 +1,8 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + fn f(callback: fn(p: *const u8)); + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/ptr_in_fnptr.stderr b/vendor/cxx/tests/ui/ptr_in_fnptr.stderr new file mode 100644 index 000000000..f429b1bd3 --- /dev/null +++ b/vendor/cxx/tests/ui/ptr_in_fnptr.stderr @@ -0,0 +1,5 @@ +error: pointer argument requires that the function pointer be marked unsafe + --> tests/ui/ptr_in_fnptr.rs:4:27 + | +4 | fn f(callback: fn(p: *const u8)); + | ^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/ptr_missing_unsafe.rs b/vendor/cxx/tests/ui/ptr_missing_unsafe.rs new file mode 100644 index 000000000..56f0007cb --- /dev/null +++ b/vendor/cxx/tests/ui/ptr_missing_unsafe.rs @@ -0,0 +1,10 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + type C; + + fn not_unsafe_ptr(c: *mut C); + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/ptr_missing_unsafe.stderr b/vendor/cxx/tests/ui/ptr_missing_unsafe.stderr new file mode 100644 index 000000000..d65481bce --- /dev/null +++ b/vendor/cxx/tests/ui/ptr_missing_unsafe.stderr @@ -0,0 +1,5 @@ +error: pointer argument requires that the function be marked unsafe + --> tests/ui/ptr_missing_unsafe.rs:6:27 + | +6 | fn not_unsafe_ptr(c: *mut C); + | ^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/ptr_no_const_mut.rs b/vendor/cxx/tests/ui/ptr_no_const_mut.rs new file mode 100644 index 000000000..eecec3fb4 --- /dev/null +++ b/vendor/cxx/tests/ui/ptr_no_const_mut.rs @@ -0,0 +1,10 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + type C; + + fn get_neither_const_nor_mut() -> *C; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/ptr_no_const_mut.stderr b/vendor/cxx/tests/ui/ptr_no_const_mut.stderr new file mode 100644 index 000000000..4b1bf06fd --- /dev/null +++ b/vendor/cxx/tests/ui/ptr_no_const_mut.stderr @@ -0,0 +1,18 @@ +error: expected `mut` or `const` keyword in raw pointer type + --> tests/ui/ptr_no_const_mut.rs:6:43 + | +6 | fn get_neither_const_nor_mut() -> *C; + | ^ + | +help: add `mut` or `const` here + | +6 | fn get_neither_const_nor_mut() -> *const C; + | +++++ +6 | fn get_neither_const_nor_mut() -> *mut C; + | +++ + +error: expected `const` or `mut` + --> tests/ui/ptr_no_const_mut.rs:6:44 + | +6 | fn get_neither_const_nor_mut() -> *C; + | ^ diff --git a/vendor/cxx/tests/ui/ptr_unsupported.rs b/vendor/cxx/tests/ui/ptr_unsupported.rs new file mode 100644 index 000000000..9d59c0330 --- /dev/null +++ b/vendor/cxx/tests/ui/ptr_unsupported.rs @@ -0,0 +1,12 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + type C; + + fn get_ptr_to_reference() -> *mut &C; + fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>; + fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/ptr_unsupported.stderr b/vendor/cxx/tests/ui/ptr_unsupported.stderr new file mode 100644 index 000000000..ea1dafd86 --- /dev/null +++ b/vendor/cxx/tests/ui/ptr_unsupported.stderr @@ -0,0 +1,17 @@ +error: C++ does not allow pointer to reference as a type + --> tests/ui/ptr_unsupported.rs:6:38 + | +6 | fn get_ptr_to_reference() -> *mut &C; + | ^^^^^^^ + +error: unsupported unique_ptr target type + --> tests/ui/ptr_unsupported.rs:7:38 + | +7 | fn get_uniqueptr_to_ptr() -> UniquePtr<*mut C>; + | ^^^^^^^^^^^^^^^^^ + +error: unsupported vector element type + --> tests/ui/ptr_unsupported.rs:8:45 + | +8 | fn get_vector_of_ptr() -> UniquePtr<CxxVector<*mut C>>; + | ^^^^^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/raw_ident_namespace.rs b/vendor/cxx/tests/ui/raw_ident_namespace.rs new file mode 100644 index 000000000..2c8286c70 --- /dev/null +++ b/vendor/cxx/tests/ui/raw_ident_namespace.rs @@ -0,0 +1,53 @@ +use cxx::{type_id, ExternType}; + +#[repr(transparent)] +pub struct QuotedRaw(usize); + +unsafe impl ExternType for QuotedRaw { + type Id = type_id!("org::r#box::implementation::QuotedRaw"); + type Kind = cxx::kind::Trivial; +} + +#[repr(transparent)] +pub struct QuotedKeyword(usize); + +unsafe impl ExternType for QuotedKeyword { + type Id = type_id!("org::box::implementation::QuotedKeyword"); + type Kind = cxx::kind::Trivial; +} + +#[repr(transparent)] +pub struct UnquotedRaw(usize); + +unsafe impl ExternType for UnquotedRaw { + type Id = type_id!(org::r#box::implementation::UnquotedRaw); + type Kind = cxx::kind::Trivial; +} + +#[repr(transparent)] +pub struct UnquotedKeyword(usize); + +unsafe impl ExternType for UnquotedKeyword { + type Id = type_id!(org::box::implementation::UnquotedKeyword); + type Kind = cxx::kind::Trivial; +} + +#[cxx::bridge] +pub mod ffi { + extern "C++" { + #[namespace = "org::r#box::implementation"] + type QuotedRaw = crate::QuotedRaw; + + #[namespace = "org::box::implementation"] + type QuotedKeyword = crate::QuotedKeyword; + + #[namespace = org::r#box::implementation] + type UnquotedRaw = crate::UnquotedRaw; + + // Not allowed by rustc (independent of cxx): + // #[namespace = org::box::implementation] + // type UnquotedKeyword = crate::UnquotedKeyword; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/raw_ident_namespace.stderr b/vendor/cxx/tests/ui/raw_ident_namespace.stderr new file mode 100644 index 000000000..86c8b6fd6 --- /dev/null +++ b/vendor/cxx/tests/ui/raw_ident_namespace.stderr @@ -0,0 +1,11 @@ +error: raw identifier `r#box` is not allowed in a quoted namespace; use `box`, or remove quotes + --> tests/ui/raw_ident_namespace.rs:7:24 + | +7 | type Id = type_id!("org::r#box::implementation::QuotedRaw"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: raw identifier `r#box` is not allowed in a quoted namespace; use `box`, or remove quotes + --> tests/ui/raw_ident_namespace.rs:38:23 + | +38 | #[namespace = "org::r#box::implementation"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/reference_to_reference.rs b/vendor/cxx/tests/ui/reference_to_reference.rs new file mode 100644 index 000000000..91fe16003 --- /dev/null +++ b/vendor/cxx/tests/ui/reference_to_reference.rs @@ -0,0 +1,13 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + type ThingC; + fn repro_c(t: &&ThingC); + } + extern "Rust" { + type ThingR; + fn repro_r(t: &&ThingR); + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/reference_to_reference.stderr b/vendor/cxx/tests/ui/reference_to_reference.stderr new file mode 100644 index 000000000..765e44271 --- /dev/null +++ b/vendor/cxx/tests/ui/reference_to_reference.stderr @@ -0,0 +1,11 @@ +error: C++ does not allow references to references + --> tests/ui/reference_to_reference.rs:5:23 + | +5 | fn repro_c(t: &&ThingC); + | ^^^^^^^^ + +error: C++ does not allow references to references + --> tests/ui/reference_to_reference.rs:9:23 + | +9 | fn repro_r(t: &&ThingR); + | ^^^^^^^^ diff --git a/vendor/cxx/tests/ui/reserved_lifetime.rs b/vendor/cxx/tests/ui/reserved_lifetime.rs new file mode 100644 index 000000000..179a4db54 --- /dev/null +++ b/vendor/cxx/tests/ui/reserved_lifetime.rs @@ -0,0 +1,10 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + type Logger; + + fn logger<'static>() -> Pin<&'static Logger>; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/reserved_lifetime.stderr b/vendor/cxx/tests/ui/reserved_lifetime.stderr new file mode 100644 index 000000000..e95826719 --- /dev/null +++ b/vendor/cxx/tests/ui/reserved_lifetime.stderr @@ -0,0 +1,5 @@ +error[E0262]: invalid lifetime parameter name: `'static` + --> tests/ui/reserved_lifetime.rs:6:19 + | +6 | fn logger<'static>() -> Pin<&'static Logger>; + | ^^^^^^^ 'static is a reserved lifetime name diff --git a/vendor/cxx/tests/ui/reserved_name.rs b/vendor/cxx/tests/ui/reserved_name.rs new file mode 100644 index 000000000..409e67c0c --- /dev/null +++ b/vendor/cxx/tests/ui/reserved_name.rs @@ -0,0 +1,16 @@ +#[cxx::bridge] +mod ffi { + struct UniquePtr { + val: usize, + } + + extern "C++" { + type Box; + } + + extern "Rust" { + type String; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/reserved_name.stderr b/vendor/cxx/tests/ui/reserved_name.stderr new file mode 100644 index 000000000..7636f872b --- /dev/null +++ b/vendor/cxx/tests/ui/reserved_name.stderr @@ -0,0 +1,17 @@ +error: reserved name + --> tests/ui/reserved_name.rs:3:12 + | +3 | struct UniquePtr { + | ^^^^^^^^^ + +error: reserved name + --> tests/ui/reserved_name.rs:8:14 + | +8 | type Box; + | ^^^ + +error: reserved name + --> tests/ui/reserved_name.rs:12:14 + | +12 | type String; + | ^^^^^^ diff --git a/vendor/cxx/tests/ui/result_no_display.rs b/vendor/cxx/tests/ui/result_no_display.rs new file mode 100644 index 000000000..b53567751 --- /dev/null +++ b/vendor/cxx/tests/ui/result_no_display.rs @@ -0,0 +1,14 @@ +#[cxx::bridge] +mod ffi { + extern "Rust" { + fn f() -> Result<()>; + } +} + +pub struct NonError; + +fn f() -> Result<(), NonError> { + Ok(()) +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/result_no_display.stderr b/vendor/cxx/tests/ui/result_no_display.stderr new file mode 100644 index 000000000..44d4b31da --- /dev/null +++ b/vendor/cxx/tests/ui/result_no_display.stderr @@ -0,0 +1,8 @@ +error[E0277]: `NonError` doesn't implement `std::fmt::Display` + --> tests/ui/result_no_display.rs:4:19 + | +4 | fn f() -> Result<()>; + | ^^^^^^^^^^ `NonError` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `NonError` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead diff --git a/vendor/cxx/tests/ui/root_namespace.rs b/vendor/cxx/tests/ui/root_namespace.rs new file mode 100644 index 000000000..886fbd946 --- /dev/null +++ b/vendor/cxx/tests/ui/root_namespace.rs @@ -0,0 +1,13 @@ +#[cxx::bridge] +mod ffi { + #[namespace = "::"] + extern "Rust" {} + + #[namespace = ""] + extern "Rust" {} + + #[namespace = ] + extern "Rust" {} +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/root_namespace.stderr b/vendor/cxx/tests/ui/root_namespace.stderr new file mode 100644 index 000000000..b834d91a0 --- /dev/null +++ b/vendor/cxx/tests/ui/root_namespace.stderr @@ -0,0 +1,5 @@ +error: expected expression, found `]` + --> tests/ui/root_namespace.rs:9:19 + | +9 | #[namespace = ] + | ^ expected expression diff --git a/vendor/cxx/tests/ui/rust_pinned.rs b/vendor/cxx/tests/ui/rust_pinned.rs new file mode 100644 index 000000000..34ca7e331 --- /dev/null +++ b/vendor/cxx/tests/ui/rust_pinned.rs @@ -0,0 +1,14 @@ +use std::marker::PhantomPinned; + +#[cxx::bridge] +mod ffi { + extern "Rust" { + type Pinned; + } +} + +pub struct Pinned { + _pinned: PhantomPinned, +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/rust_pinned.stderr b/vendor/cxx/tests/ui/rust_pinned.stderr new file mode 100644 index 000000000..a0fc03382 --- /dev/null +++ b/vendor/cxx/tests/ui/rust_pinned.stderr @@ -0,0 +1,17 @@ +error[E0277]: `PhantomPinned` cannot be unpinned + --> tests/ui/rust_pinned.rs:6:14 + | +6 | type Pinned; + | ^^^^^^ within `Pinned`, the trait `Unpin` is not implemented for `PhantomPinned` + | + = note: consider using `Box::pin` +note: required because it appears within the type `Pinned` + --> tests/ui/rust_pinned.rs:10:12 + | +10 | pub struct Pinned { + | ^^^^^^ +note: required by a bound in `__AssertUnpin` + --> tests/ui/rust_pinned.rs:6:9 + | +6 | type Pinned; + | ^^^^^^^^^^^^ required by this bound in `__AssertUnpin` diff --git a/vendor/cxx/tests/ui/slice_of_type_alias.rs b/vendor/cxx/tests/ui/slice_of_type_alias.rs new file mode 100644 index 000000000..a7bbc1147 --- /dev/null +++ b/vendor/cxx/tests/ui/slice_of_type_alias.rs @@ -0,0 +1,30 @@ +use cxx::{type_id, ExternType}; + +#[repr(C)] +struct ElementTrivial(usize); + +#[repr(C)] +struct ElementOpaque(usize); + +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + type ElementTrivial = crate::ElementTrivial; + type ElementOpaque = crate::ElementOpaque; + + fn f(slice: &mut [ElementTrivial]); + fn g(slice: &[ElementOpaque]); + } +} + +unsafe impl ExternType for ElementTrivial { + type Id = type_id!("ElementTrivial"); + type Kind = cxx::kind::Trivial; +} + +unsafe impl ExternType for ElementOpaque { + type Id = type_id!("ElementOpaque"); + type Kind = cxx::kind::Opaque; +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/slice_of_type_alias.stderr b/vendor/cxx/tests/ui/slice_of_type_alias.stderr new file mode 100644 index 000000000..9339da37a --- /dev/null +++ b/vendor/cxx/tests/ui/slice_of_type_alias.stderr @@ -0,0 +1,16 @@ +error[E0271]: type mismatch resolving `<ElementOpaque as ExternType>::Kind == Trivial` + --> tests/ui/slice_of_type_alias.rs:13:14 + | +13 | type ElementOpaque = crate::ElementOpaque; + | ^^^^^^^^^^^^^ type mismatch resolving `<ElementOpaque as ExternType>::Kind == Trivial` + | +note: expected this to be `Trivial` + --> tests/ui/slice_of_type_alias.rs:27:17 + | +27 | type Kind = cxx::kind::Opaque; + | ^^^^^^^^^^^^^^^^^ +note: required by a bound in `verify_extern_kind` + --> src/extern_type.rs + | + | pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {} + | ^^^^^^^^^^^ required by this bound in `verify_extern_kind` diff --git a/vendor/cxx/tests/ui/slice_unsupported.rs b/vendor/cxx/tests/ui/slice_unsupported.rs new file mode 100644 index 000000000..7a148dd7e --- /dev/null +++ b/vendor/cxx/tests/ui/slice_unsupported.rs @@ -0,0 +1,10 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + type Opaque; + + fn f(_: &mut [Opaque]); + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/slice_unsupported.stderr b/vendor/cxx/tests/ui/slice_unsupported.stderr new file mode 100644 index 000000000..b781bfd46 --- /dev/null +++ b/vendor/cxx/tests/ui/slice_unsupported.stderr @@ -0,0 +1,11 @@ +error: unsupported &mut [T] element type: opaque C++ type is not supported yet + --> tests/ui/slice_unsupported.rs:6:17 + | +6 | fn f(_: &mut [Opaque]); + | ^^^^^^^^^^^^^ + +error: needs a cxx::ExternType impl in order to be used as a slice element in &mut [Opaque] + --> tests/ui/slice_unsupported.rs:4:9 + | +4 | type Opaque; + | ^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/struct_cycle.rs b/vendor/cxx/tests/ui/struct_cycle.rs new file mode 100644 index 000000000..e74c2b1ca --- /dev/null +++ b/vendor/cxx/tests/ui/struct_cycle.rs @@ -0,0 +1,34 @@ +#[cxx::bridge] +mod ffi { + struct Node0 { + i: i32, + } + + struct Node1 { + node2: Node2, + vec: Vec<Node3>, + } + + struct Node2 { + node4: Node4, + } + + struct Node3 { + node1: Node1, + } + + struct Node4 { + node0: Node0, + node5: Node5, + } + + struct Node5 { + node2: Node2, + } + + struct Node6 { + node2: Node2, + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/struct_cycle.stderr b/vendor/cxx/tests/ui/struct_cycle.stderr new file mode 100644 index 000000000..9ee2d8316 --- /dev/null +++ b/vendor/cxx/tests/ui/struct_cycle.stderr @@ -0,0 +1,23 @@ +error: unsupported cyclic data structure + --> tests/ui/struct_cycle.rs:26:9 + | +26 | node2: Node2, + | ^^^^^^^^^^^^ + +error: unsupported cyclic data structure + --> tests/ui/struct_cycle.rs:22:9 + | +22 | node5: Node5, + | ^^^^^^^^^^^^ + +error: unsupported cyclic data structure + --> tests/ui/struct_cycle.rs:13:9 + | +13 | node4: Node4, + | ^^^^^^^^^^^^ + +error: unsupported cyclic data structure + --> tests/ui/struct_cycle.rs:8:9 + | +8 | node2: Node2, + | ^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/type_alias_rust.rs b/vendor/cxx/tests/ui/type_alias_rust.rs new file mode 100644 index 000000000..67df48926 --- /dev/null +++ b/vendor/cxx/tests/ui/type_alias_rust.rs @@ -0,0 +1,9 @@ +#[cxx::bridge] +mod ffi { + extern "Rust" { + /// Incorrect. + type Alias = crate::Type; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/type_alias_rust.stderr b/vendor/cxx/tests/ui/type_alias_rust.stderr new file mode 100644 index 000000000..8cf9a56fb --- /dev/null +++ b/vendor/cxx/tests/ui/type_alias_rust.stderr @@ -0,0 +1,5 @@ +error: type alias in extern "Rust" block is not supported + --> tests/ui/type_alias_rust.rs:5:9 + | +5 | type Alias = crate::Type; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/unique_ptr_as_mut.rs b/vendor/cxx/tests/ui/unique_ptr_as_mut.rs new file mode 100644 index 000000000..d2c758a9f --- /dev/null +++ b/vendor/cxx/tests/ui/unique_ptr_as_mut.rs @@ -0,0 +1,23 @@ +use cxx::UniquePtr; + +#[cxx::bridge] +mod ffi { + struct Shared { + x: i32, + } + + extern "C++" { + type Opaque; + } + + impl UniquePtr<Shared> {} + impl UniquePtr<Opaque> {} +} + +fn main() { + let mut shared = UniquePtr::<ffi::Shared>::null(); + let _: &mut ffi::Shared = &mut shared; + + let mut opaque = UniquePtr::<ffi::Opaque>::null(); + let _: &mut ffi::Opaque = &mut opaque; +} diff --git a/vendor/cxx/tests/ui/unique_ptr_as_mut.stderr b/vendor/cxx/tests/ui/unique_ptr_as_mut.stderr new file mode 100644 index 000000000..a8248dbe6 --- /dev/null +++ b/vendor/cxx/tests/ui/unique_ptr_as_mut.stderr @@ -0,0 +1,7 @@ +error[E0596]: cannot borrow data in dereference of `UniquePtr<ffi::Opaque>` as mutable + --> tests/ui/unique_ptr_as_mut.rs:22:31 + | +22 | let _: &mut ffi::Opaque = &mut opaque; + | ^^^^^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `UniquePtr<ffi::Opaque>` diff --git a/vendor/cxx/tests/ui/unique_ptr_to_opaque.rs b/vendor/cxx/tests/ui/unique_ptr_to_opaque.rs new file mode 100644 index 000000000..5226ca81b --- /dev/null +++ b/vendor/cxx/tests/ui/unique_ptr_to_opaque.rs @@ -0,0 +1,23 @@ +mod outside { + #[repr(C)] + pub struct C { + pub a: u8, + } + unsafe impl cxx::ExternType for C { + type Id = cxx::type_id!("C"); + type Kind = cxx::kind::Opaque; + } +} + +#[cxx::bridge] +mod ffi { + extern "C++" { + type C = crate::outside::C; + } + + impl UniquePtr<C> {} +} + +fn main() { + cxx::UniquePtr::new(outside::C { a: 4 }); +} diff --git a/vendor/cxx/tests/ui/unique_ptr_to_opaque.stderr b/vendor/cxx/tests/ui/unique_ptr_to_opaque.stderr new file mode 100644 index 000000000..3c121e54c --- /dev/null +++ b/vendor/cxx/tests/ui/unique_ptr_to_opaque.stderr @@ -0,0 +1,18 @@ +error[E0271]: type mismatch resolving `<C as ExternType>::Kind == Trivial` + --> tests/ui/unique_ptr_to_opaque.rs:22:25 + | +22 | cxx::UniquePtr::new(outside::C { a: 4 }); + | ------------------- ^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<C as ExternType>::Kind == Trivial` + | | + | required by a bound introduced by this call + | +note: expected this to be `Trivial` + --> tests/ui/unique_ptr_to_opaque.rs:8:21 + | +8 | type Kind = cxx::kind::Opaque; + | ^^^^^^^^^^^^^^^^^ +note: required by a bound in `UniquePtr::<T>::new` + --> src/unique_ptr.rs + | + | T: ExternType<Kind = Trivial>, + | ^^^^^^^^^^^^^^ required by this bound in `UniquePtr::<T>::new` diff --git a/vendor/cxx/tests/ui/unique_ptr_twice.rs b/vendor/cxx/tests/ui/unique_ptr_twice.rs new file mode 100644 index 000000000..14c6f62a4 --- /dev/null +++ b/vendor/cxx/tests/ui/unique_ptr_twice.rs @@ -0,0 +1,19 @@ +#[cxx::bridge] +mod here { + extern "C++" { + type C; + } + + impl UniquePtr<C> {} +} + +#[cxx::bridge] +mod there { + extern "C++" { + type C = crate::here::C; + } + + impl UniquePtr<C> {} +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/unique_ptr_twice.stderr b/vendor/cxx/tests/ui/unique_ptr_twice.stderr new file mode 100644 index 000000000..b21791fbe --- /dev/null +++ b/vendor/cxx/tests/ui/unique_ptr_twice.stderr @@ -0,0 +1,8 @@ +error[E0119]: conflicting implementations of trait `UniquePtrTarget` for type `here::C` + --> tests/ui/unique_ptr_twice.rs:16:5 + | +7 | impl UniquePtr<C> {} + | ---------------- first implementation here +... +16 | impl UniquePtr<C> {} + | ^^^^^^^^^^^^^^^^ conflicting implementation for `here::C` diff --git a/vendor/cxx/tests/ui/unnamed_receiver.rs b/vendor/cxx/tests/ui/unnamed_receiver.rs new file mode 100644 index 000000000..5f53a0a5f --- /dev/null +++ b/vendor/cxx/tests/ui/unnamed_receiver.rs @@ -0,0 +1,14 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + type One; + type Two; + fn f(&mut self); + } + + extern "Rust" { + fn f(self: &Self); + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/unnamed_receiver.stderr b/vendor/cxx/tests/ui/unnamed_receiver.stderr new file mode 100644 index 000000000..d903b2311 --- /dev/null +++ b/vendor/cxx/tests/ui/unnamed_receiver.stderr @@ -0,0 +1,11 @@ +error: unnamed receiver type is only allowed if the surrounding extern block contains exactly one extern type; use `self: &mut TheType` + --> tests/ui/unnamed_receiver.rs:6:14 + | +6 | fn f(&mut self); + | ^^^^^^^^^ + +error: unnamed receiver type is only allowed if the surrounding extern block contains exactly one extern type; use `self: &TheType` + --> tests/ui/unnamed_receiver.rs:10:20 + | +10 | fn f(self: &Self); + | ^^^^^ diff --git a/vendor/cxx/tests/ui/unpin_impl.rs b/vendor/cxx/tests/ui/unpin_impl.rs new file mode 100644 index 000000000..129fcb11d --- /dev/null +++ b/vendor/cxx/tests/ui/unpin_impl.rs @@ -0,0 +1,10 @@ +#[cxx::bridge] +mod ffi { + extern "C++" { + type Opaque; + } +} + +impl Unpin for ffi::Opaque {} + +fn main() {} diff --git a/vendor/cxx/tests/ui/unpin_impl.stderr b/vendor/cxx/tests/ui/unpin_impl.stderr new file mode 100644 index 000000000..afe5a8066 --- /dev/null +++ b/vendor/cxx/tests/ui/unpin_impl.stderr @@ -0,0 +1,18 @@ +error[E0282]: type annotations needed + --> tests/ui/unpin_impl.rs:4:14 + | +4 | type Opaque; + | ^^^^^^ cannot infer type + +error[E0283]: type annotations needed + --> tests/ui/unpin_impl.rs:1:1 + | +1 | #[cxx::bridge] + | ^^^^^^^^^^^^^^ cannot infer type + | +note: multiple `impl`s satisfying `ffi::Opaque: __AmbiguousIfImpl<_>` found + --> tests/ui/unpin_impl.rs:1:1 + | +1 | #[cxx::bridge] + | ^^^^^^^^^^^^^^ + = note: this error originates in the attribute macro `cxx::bridge` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/vendor/cxx/tests/ui/unrecognized_receiver.rs b/vendor/cxx/tests/ui/unrecognized_receiver.rs new file mode 100644 index 000000000..eee825932 --- /dev/null +++ b/vendor/cxx/tests/ui/unrecognized_receiver.rs @@ -0,0 +1,8 @@ +#[cxx::bridge] +mod ffi { + unsafe extern "C++" { + fn f(self: &Unrecognized); + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/unrecognized_receiver.stderr b/vendor/cxx/tests/ui/unrecognized_receiver.stderr new file mode 100644 index 000000000..bc645fec2 --- /dev/null +++ b/vendor/cxx/tests/ui/unrecognized_receiver.stderr @@ -0,0 +1,5 @@ +error: unrecognized receiver type + --> tests/ui/unrecognized_receiver.rs:4:20 + | +4 | fn f(self: &Unrecognized); + | ^^^^^^^^^^^^^ diff --git a/vendor/cxx/tests/ui/unsupported_elided.rs b/vendor/cxx/tests/ui/unsupported_elided.rs new file mode 100644 index 000000000..403331968 --- /dev/null +++ b/vendor/cxx/tests/ui/unsupported_elided.rs @@ -0,0 +1,20 @@ +use std::marker::PhantomData; + +#[cxx::bridge] +mod ffi { + extern "Rust" { + type T; + + fn f(t: &T) -> &str; + } +} + +pub struct T<'a> { + _lifetime: PhantomData<&'a ()>, +} + +fn f<'a>(_t: &T<'a>) -> &'a str { + "" +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/unsupported_elided.stderr b/vendor/cxx/tests/ui/unsupported_elided.stderr new file mode 100644 index 000000000..4ccac6fb7 --- /dev/null +++ b/vendor/cxx/tests/ui/unsupported_elided.stderr @@ -0,0 +1,22 @@ +error[E0726]: implicit elided lifetime not allowed here + --> tests/ui/unsupported_elided.rs:6:14 + | +6 | type T; + | ^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +6 | type T<'_>; + | ++++ + +error[E0106]: missing lifetime specifier + --> tests/ui/unsupported_elided.rs:8:24 + | +8 | fn f(t: &T) -> &str; + | -- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say which one of `t`'s 2 lifetimes it is borrowed from +help: consider introducing a named lifetime parameter + | +8 | fn f<'a>(t: &'a T<'a>) -> &'a str; + | ++++ ++ ++++ ++ diff --git a/vendor/cxx/tests/ui/vec_opaque.rs b/vendor/cxx/tests/ui/vec_opaque.rs new file mode 100644 index 000000000..d0b279cf6 --- /dev/null +++ b/vendor/cxx/tests/ui/vec_opaque.rs @@ -0,0 +1,34 @@ +#[cxx::bridge] +mod handle { + extern "C++" { + type Job; + } +} + +#[cxx::bridge] +mod ffi1 { + extern "C++" { + type Job; + } + + extern "Rust" { + fn f() -> Vec<Job>; + } +} + +#[cxx::bridge] +mod ffi2 { + extern "C++" { + type Job = crate::handle::Job; + } + + extern "Rust" { + fn f() -> Vec<Job>; + } +} + +fn f() -> Vec<handle::Job> { + unimplemented!() +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/vec_opaque.stderr b/vendor/cxx/tests/ui/vec_opaque.stderr new file mode 100644 index 000000000..ae01adfc3 --- /dev/null +++ b/vendor/cxx/tests/ui/vec_opaque.stderr @@ -0,0 +1,23 @@ +error: Rust Vec containing C++ type is not supported yet + --> tests/ui/vec_opaque.rs:15:19 + | +15 | fn f() -> Vec<Job>; + | ^^^^^^^^ + +error: needs a cxx::ExternType impl in order to be used as a vector element in Vec<Job> + --> tests/ui/vec_opaque.rs:11:9 + | +11 | type Job; + | ^^^^^^^^ + +error[E0271]: type mismatch resolving `<Job as ExternType>::Kind == Trivial` + --> tests/ui/vec_opaque.rs:22:14 + | +22 | type Job = crate::handle::Job; + | ^^^ expected `Trivial`, found `Opaque` + | +note: required by a bound in `verify_extern_kind` + --> src/extern_type.rs + | + | pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {} + | ^^^^^^^^^^^ required by this bound in `verify_extern_kind` diff --git a/vendor/cxx/tests/ui/vector_autotraits.rs b/vendor/cxx/tests/ui/vector_autotraits.rs new file mode 100644 index 000000000..cc918d58c --- /dev/null +++ b/vendor/cxx/tests/ui/vector_autotraits.rs @@ -0,0 +1,21 @@ +use cxx::CxxVector; + +#[cxx::bridge] +mod ffi { + extern "C++" { + type ThreadSafe; + type NotThreadSafe; + } + + impl CxxVector<ThreadSafe> {} + impl CxxVector<NotThreadSafe> {} +} + +unsafe impl Send for ffi::ThreadSafe {} + +fn assert_send<T: Send>() {} + +fn main() { + assert_send::<CxxVector<ffi::ThreadSafe>>(); + assert_send::<CxxVector<ffi::NotThreadSafe>>(); +} diff --git a/vendor/cxx/tests/ui/vector_autotraits.stderr b/vendor/cxx/tests/ui/vector_autotraits.stderr new file mode 100644 index 000000000..8851cedc1 --- /dev/null +++ b/vendor/cxx/tests/ui/vector_autotraits.stderr @@ -0,0 +1,22 @@ +error[E0277]: `*const cxx::void` cannot be sent between threads safely + --> tests/ui/vector_autotraits.rs:20:19 + | +20 | assert_send::<CxxVector<ffi::NotThreadSafe>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const cxx::void` cannot be sent between threads safely + | + = help: within `CxxVector<NotThreadSafe>`, the trait `Send` is not implemented for `*const cxx::void` + = note: required because it appears within the type `[*const void; 0]` + = note: required because it appears within the type `Opaque` +note: required because it appears within the type `NotThreadSafe` + --> tests/ui/vector_autotraits.rs:7:14 + | +7 | type NotThreadSafe; + | ^^^^^^^^^^^^^ + = note: required because it appears within the type `[NotThreadSafe]` + = note: required because it appears within the type `PhantomData<[NotThreadSafe]>` + = note: required because it appears within the type `CxxVector<NotThreadSafe>` +note: required by a bound in `assert_send` + --> tests/ui/vector_autotraits.rs:16:19 + | +16 | fn assert_send<T: Send>() {} + | ^^^^ required by this bound in `assert_send` diff --git a/vendor/cxx/tests/ui/wrong_type_id.rs b/vendor/cxx/tests/ui/wrong_type_id.rs new file mode 100644 index 000000000..9137e5166 --- /dev/null +++ b/vendor/cxx/tests/ui/wrong_type_id.rs @@ -0,0 +1,15 @@ +#[cxx::bridge(namespace = "folly")] +mod here { + extern "C++" { + type StringPiece; + } +} + +#[cxx::bridge(namespace = "folly")] +mod there { + extern "C++" { + type ByteRange = crate::here::StringPiece; + } +} + +fn main() {} diff --git a/vendor/cxx/tests/ui/wrong_type_id.stderr b/vendor/cxx/tests/ui/wrong_type_id.stderr new file mode 100644 index 000000000..d3ed3a0c1 --- /dev/null +++ b/vendor/cxx/tests/ui/wrong_type_id.stderr @@ -0,0 +1,13 @@ +error[E0271]: type mismatch resolving `<StringPiece as ExternType>::Id == (f, o, l, l, y, (), B, y, t, e, ..., ..., ..., ..., ...)` + --> tests/ui/wrong_type_id.rs:11:14 + | +11 | type ByteRange = crate::here::StringPiece; + | ^^^^^^^^^ expected a tuple with 15 elements, found one with 17 elements + | + = note: expected tuple `(f, o, l, l, y, (), B, y, t, e, R, a, n, g, e)` + found tuple `(f, o, l, l, y, (), S, t, r, i, n, g, P, i, e, c, e)` +note: required by a bound in `verify_extern_type` + --> src/extern_type.rs + | + | pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {} + | ^^^^^^^ required by this bound in `verify_extern_type` diff --git a/vendor/cxx/tests/unique_ptr.rs b/vendor/cxx/tests/unique_ptr.rs new file mode 100644 index 000000000..e5eb66bcd --- /dev/null +++ b/vendor/cxx/tests/unique_ptr.rs @@ -0,0 +1,8 @@ +use cxx::{CxxString, UniquePtr}; + +#[test] +#[should_panic = "called deref on a null UniquePtr<CxxString>"] +fn test_deref_null() { + let unique_ptr = UniquePtr::<CxxString>::null(); + let _: &CxxString = &unique_ptr; +} diff --git a/vendor/cxx/tools/bazel/BUILD b/vendor/cxx/tools/bazel/BUILD new file mode 100644 index 000000000..d42fc71c8 --- /dev/null +++ b/vendor/cxx/tools/bazel/BUILD @@ -0,0 +1,7 @@ +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") + +bzl_library( + name = "bzl_srcs", + srcs = glob(["**/*.bzl"]), + visibility = ["//visibility:public"], +) diff --git a/vendor/cxx/tools/bazel/rust_cxx_bridge.bzl b/vendor/cxx/tools/bazel/rust_cxx_bridge.bzl new file mode 100644 index 000000000..c7d07e8a1 --- /dev/null +++ b/vendor/cxx/tools/bazel/rust_cxx_bridge.bzl @@ -0,0 +1,49 @@ +# buildifier: disable=module-docstring +load("@bazel_skylib//rules:run_binary.bzl", "run_binary") +load("@rules_cc//cc:defs.bzl", "cc_library") + +def rust_cxx_bridge(name, src, deps = []): + """A macro defining a cxx bridge library + + Args: + name (string): The name of the new target + src (string): The rust source file to generate a bridge for + deps (list, optional): A list of dependencies for the underlying cc_library. Defaults to []. + """ + native.alias( + name = "%s/header" % name, + actual = src + ".h", + ) + + native.alias( + name = "%s/source" % name, + actual = src + ".cc", + ) + + run_binary( + name = "%s/generated" % name, + srcs = [src], + outs = [ + src + ".h", + src + ".cc", + ], + args = [ + "$(location %s)" % src, + "-o", + "$(location %s.h)" % src, + "-o", + "$(location %s.cc)" % src, + ], + tool = "@cxx.rs//:codegen", + ) + + cc_library( + name = name, + srcs = [src + ".cc"], + deps = deps + [":%s/include" % name], + ) + + cc_library( + name = "%s/include" % name, + hdrs = [src + ".h"], + ) diff --git a/vendor/cxx/tools/buck/buildscript.bzl b/vendor/cxx/tools/buck/buildscript.bzl new file mode 100644 index 000000000..e4d5e1e4e --- /dev/null +++ b/vendor/cxx/tools/buck/buildscript.bzl @@ -0,0 +1,17 @@ +def buildscript_args( + name: str.type, + package_name: str.type, + buildscript_rule: str.type, + outfile: str.type, + version: str.type, + cfgs: [str.type] = [], + features: [str.type] = []): + _ = package_name + _ = version + _ = cfgs + _ = features + native.genrule( + name = name, + out = outfile, + cmd = "env RUSTC=rustc TARGET= $(exe %s) | sed -n s/^cargo:rustc-cfg=/--cfg=/p > ${OUT}" % buildscript_rule, + ) diff --git a/vendor/cxx/tools/buck/rust_cxx_bridge.bzl b/vendor/cxx/tools/buck/rust_cxx_bridge.bzl new file mode 100644 index 000000000..18bb24585 --- /dev/null +++ b/vendor/cxx/tools/buck/rust_cxx_bridge.bzl @@ -0,0 +1,35 @@ +def rust_cxx_bridge( + name: str.type, + src: str.type, + deps: [str.type] = []): + native.genrule( + name = "%s/header" % name, + out = src + ".h", + cmd = "cp $(location :%s/generated)/generated.h ${OUT}" % name, + ) + + native.genrule( + name = "%s/source" % name, + out = src + ".cc", + cmd = "cp $(location :%s/generated)/generated.cc ${OUT}" % name, + ) + + native.genrule( + name = "%s/generated" % name, + srcs = [src], + out = ".", + cmd = "$(exe //:codegen) ${SRCS} -o ${OUT}/generated.h -o ${OUT}/generated.cc", + type = "cxxbridge", + ) + + native.cxx_library( + name = name, + srcs = [":%s/source" % name], + preferred_linkage = "static", + exported_deps = deps + [":%s/include" % name], + ) + + native.cxx_library( + name = "%s/include" % name, + exported_headers = [":%s/header" % name], + ) diff --git a/vendor/cxx/tools/buck/third_party.bzl b/vendor/cxx/tools/buck/third_party.bzl new file mode 100644 index 000000000..84e5ca8f9 --- /dev/null +++ b/vendor/cxx/tools/buck/third_party.bzl @@ -0,0 +1,5 @@ +def third_party_rust_library(**kwargs): + native.rust_library( + doctests = False, + **kwargs + ) diff --git a/vendor/cxx/tools/buck/toolchains/BUCK b/vendor/cxx/tools/buck/toolchains/BUCK new file mode 100644 index 000000000..6984a86b6 --- /dev/null +++ b/vendor/cxx/tools/buck/toolchains/BUCK @@ -0,0 +1,25 @@ +load("@prelude//toolchains:cxx.bzl", "system_cxx_toolchain") +load("@prelude//toolchains:genrule.bzl", "system_genrule_toolchain") +load("@prelude//toolchains:python.bzl", "system_python_bootstrap_toolchain") +load("@prelude//toolchains:rust.bzl", "system_rust_toolchain") + +system_cxx_toolchain( + name = "cxx", + visibility = ["PUBLIC"], +) + +system_genrule_toolchain( + name = "genrule", + visibility = ["PUBLIC"], +) + +system_python_bootstrap_toolchain( + name = "python_bootstrap", + visibility = ["PUBLIC"], +) + +system_rust_toolchain( + name = "rust", + default_edition = None, + visibility = ["PUBLIC"], +) diff --git a/vendor/cxx/tools/cargo/build.rs b/vendor/cxx/tools/cargo/build.rs new file mode 100644 index 000000000..401c74186 --- /dev/null +++ b/vendor/cxx/tools/cargo/build.rs @@ -0,0 +1,73 @@ +use std::io::{self, Write}; +#[cfg(windows)] +use std::os::windows::fs as windows; +use std::path::Path; +use std::process; +#[cfg(windows)] +use std::{env, fs}; + +const MISSING: &str = " +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When building `cxx` from a git clone, git's symlink support needs +to be enabled on platforms that have it off by default (Windows). +Either use: + + $ git config --global core.symlinks true + +prior to cloning, or else use: + + $ git clone -c core.symlinks=true https://github.com/dtolnay/cxx + +for the clone. + +Symlinks are only required when compiling locally from a clone of +the git repository---they are NOT required when building `cxx` as +a Cargo-managed (possibly transitive) build dependency downloaded +through crates.io. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +"; + +#[cfg(windows)] +const DENIED: &str = " +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When building `cxx` from a git clone on Windows we need Developer +Mode enabled for symlink support. + +To enable Developer Mode: go under Settings to Update & Security, +then 'For developers', and turn on the toggle for Developer Mode. + +For more explanation of symlinks in Windows, see these resources: +> https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/ +> https://docs.microsoft.com/windows/uwp/get-started/enable-your-device-for-development + +Symlinks are only required when compiling locally from a clone of +the git repository---they are NOT required when building `cxx` as +a Cargo-managed (possibly transitive) build dependency downloaded +through crates.io. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +"; + +fn main() { + if Path::new("src/syntax/mod.rs").exists() { + return; + } + + #[allow(unused_mut)] + let mut message = MISSING; + + #[cfg(windows)] + if let Some(out_dir) = env::var_os("OUT_DIR") { + let parent_dir = Path::new(&out_dir).join("symlink"); + let original_dir = parent_dir.join("original"); + let link_dir = parent_dir.join("link"); + if fs::create_dir_all(&original_dir).is_ok() + && (!link_dir.exists() || fs::remove_dir(&link_dir).is_ok()) + && windows::symlink_dir(&original_dir, &link_dir).is_err() + { + message = DENIED; + } + } + + let _ = io::stderr().write_all(message.as_bytes()); + process::exit(1); +} |