diff options
Diffstat (limited to 'rust/vendor/widestring')
-rw-r--r-- | rust/vendor/widestring/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | rust/vendor/widestring/CHANGELOG.md | 93 | ||||
-rw-r--r-- | rust/vendor/widestring/Cargo.toml | 38 | ||||
-rw-r--r-- | rust/vendor/widestring/LICENSE-APACHE | 201 | ||||
-rw-r--r-- | rust/vendor/widestring/LICENSE-MIT | 25 | ||||
-rw-r--r-- | rust/vendor/widestring/README.md | 37 | ||||
-rw-r--r-- | rust/vendor/widestring/appveyor.yml | 117 | ||||
-rw-r--r-- | rust/vendor/widestring/src/lib.rs | 238 | ||||
-rw-r--r-- | rust/vendor/widestring/src/platform/mod.rs | 9 | ||||
-rw-r--r-- | rust/vendor/widestring/src/platform/other.rs | 9 | ||||
-rw-r--r-- | rust/vendor/widestring/src/platform/windows.rs | 11 | ||||
-rw-r--r-- | rust/vendor/widestring/src/ucstr.rs | 538 | ||||
-rw-r--r-- | rust/vendor/widestring/src/ucstring.rs | 1570 | ||||
-rw-r--r-- | rust/vendor/widestring/src/ustr.rs | 359 | ||||
-rw-r--r-- | rust/vendor/widestring/src/ustring.rs | 785 |
15 files changed, 4031 insertions, 0 deletions
diff --git a/rust/vendor/widestring/.cargo-checksum.json b/rust/vendor/widestring/.cargo-checksum.json new file mode 100644 index 0000000..72e3bd5 --- /dev/null +++ b/rust/vendor/widestring/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"d5db02376a17a8c61c62ebfd2e539e90e3b97f68023c807e18eb76ae60955a42","Cargo.toml":"a1280c718ed6dda5782d089934860e2f1aa37fcfbe8ece66f07fbf9bd0aa8d99","LICENSE-APACHE":"c144680885b29e4719e2a51f0aab5439a1e02d980692b5aaf086cae12727f28b","LICENSE-MIT":"54c0366c7f8643c8502618e7f02b4176f28c834a6b0315b969477720b65e183f","README.md":"299439369a51c6d39bdd2f9c1dc8c97e2c1b223f3780d6672fd195ef89c62f25","appveyor.yml":"16adc84ee7445eab7debc2e91c47800791df15d18c505516e8aac53704291df9","src/lib.rs":"5250d02025395983a2ab16c86b95d608b02334b222045cd581e9f00b421fd47a","src/platform/mod.rs":"370e032d7f43b5893d40350ac0428ec494af68c84d9f37b9ff2f93a5d7176550","src/platform/other.rs":"bc67c5aa65b8245813f4d2cdc1f0f43ceb9e72721be120d3b40c28447f47b5f2","src/platform/windows.rs":"1739ffaf89872aa12496a674e94be916ed21e44e25ce768cfbd29d9aa48497c7","src/ucstr.rs":"c29a35edbff145e4b0a20916afc7fc7f6ace13675f08dbbfb5abf742d0589b93","src/ucstring.rs":"2e096297d9e17d568559261eae44c82c8d49e349645b0af9b9ea2b0762341880","src/ustr.rs":"c063d42a049a17804ec82a4dd5becbbf24bebcab781c55a8bb128a2273e0cb41","src/ustring.rs":"63e1ab89f990b1d0b9d184281783749a6f23d2faa484f4d0f0e68f99d9927ae9"},"package":"c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"}
\ No newline at end of file diff --git a/rust/vendor/widestring/CHANGELOG.md b/rust/vendor/widestring/CHANGELOG.md new file mode 100644 index 0000000..cc0aa13 --- /dev/null +++ b/rust/vendor/widestring/CHANGELOG.md @@ -0,0 +1,93 @@ +# Changelog + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.4.3] - 2020-10-05 <a name="0.4.3"></a> +### Fixed +- Fixed undefined behaviours and cleaned up clippy warnings. By [@joshwd36]. + +## [0.4.2] - 2020-06-09 <a name="0.4.2"></a> +### Fixed +- Fixed compile errors on pre-1.36.0 Rust due to unstable `alloc` crate. Minimum supported version + is Rust 1.34.2, the rust version for Debian stable. Fixes [#14]. + +## [0.4.1] - 2020-06-08 <a name="0.4.1"></a> +### ***Yanked*** +### Changed +- Now supports `no_std`. Added the `std` and `alloc` features, enabled by default. `U16String`, + `U32String`, `U16CString`, and `U32CString` and their aliases all require the `alloc` or `std` + feature. By [@nicbn]. + +## [0.4.0] - 2018-08-18 <a name="0.4.0"></a> +### Added +- New `U32String`, `U32Str`, `U32CString`, and `U32CStr` types for dealing with UTF-32 FFI. These + new types are roughly equivalent to the existing UTF-16 types. +- `WideChar` is a type alias to `u16` on Windows but `u32` on non-Windows platforms. +- The generic types `UString`, `UStr`, `UCString` and `UCStr` are used to implement the string + types. + +### Changed +- **Breaking Change** Existing wide string types have been renamed to `U16String`, `U16Str`, + `U16CString`, and `U16CStr` (previously `WideString`, `WideStr`, etc.). Some function have + also been renamed to reflect this change (`wide_str` to `u16_str`, etc.). +- **Breaking Change** `WideString`, `WideStr`, `WideCString`, and `WideCStr` are now type aliases + that vary between platforms. On Windows, these are aliases to the `U16` types and are equivalent + to the previous version, but on non-Windows platforms these alias the new `U32` types instead. + See crate documentation for more details. + +## [0.3.0] - 2018-03-17 <a name="0.3.0"></a> +### Added +- Additional unchecked functions on `WideCString`. +- All types now implement `Default`. +- `WideString::shrink_to_fit` +- `WideString::into_boxed_wide_str` and `Box<WideStr>::into_wide_string`. +- `WideCString::into_boxed_wide_c_str` and `Box<WideCStr>::into_wide_c_string`. +- `From` and `Default` implementations for boxed `WideStr` and boxed `WideCStr`. + +### Changed +- Renamed `WideCString::from_vec` to replace `WideCString::new`. To create empty string, use + `WideCString::default()` now. +- `WideCString` now implements `Drop`, which sets the string to an empty string to prevent invalid + unsafe code from working correctly when it should otherwise break. Also see `Drop` implementation + of `CString`. +- Writing changelog manually. +- Upgraded winapi dev dependency. +- Now requires at least Rust 1.17+ to compile (previously, was Rust 1.8). + +## [0.2.2] - 2016-09-09 <a name="0.2.2"></a> +### Fixed +- Make `WideCString::into_raw` correctly forget the original self. + +## [0.2.1] - 2016-08-12 <a name="0.2.1"></a> +### Added +- `into_raw`/`from_raw` on `WideCString`. Closes [#2]. + +## [0.2.0] - 2016-05-31 <a name="0.2.0"></a> +### Added +- `Default` trait to wide strings. +- Traits for conversion of strings to `Cow`. +### Changed +- Methods & traits to bring to parity with Rust 1.9 string APIs. + +## 0.1.0 - 2016-02-06 <a name="0.1.0"></a> +### Added +- Initial release. + +[#2]: https://github.com/starkat99/widestring-rs/issues/2 +[#14]: https://github.com/starkat99/widestring-rs/issues/14 + +[@nicbn]: https://github.com/nicbn +[@joshwd36]: https://github.com/joshwb36 + +[Unreleased]: https://github.com/starkat99/widestring-rs/compare/v0.4.3...HEAD +[0.4.3]: https://github.com/starkat99/widestring-rs/compare/v0.4.2...v0.4.3 +[0.4.2]: https://github.com/starkat99/widestring-rs/compare/v0.4.1...v0.4.2 +[0.4.1]: https://github.com/starkat99/widestring-rs/compare/v0.4.0...v0.4.1 +[0.4.0]: https://github.com/starkat99/widestring-rs/compare/v0.3.0...v0.4.0 +[0.3.0]: https://github.com/starkat99/widestring-rs/compare/v0.2.2...v0.3.0 +[0.2.2]: https://github.com/starkat99/widestring-rs/compare/v0.2.1...v0.2.2 +[0.2.1]: https://github.com/starkat99/widestring-rs/compare/v0.2.0...v0.2.1 +[0.2.0]: https://github.com/starkat99/widestring-rs/compare/v0.1.0...v0.2.0 diff --git a/rust/vendor/widestring/Cargo.toml b/rust/vendor/widestring/Cargo.toml new file mode 100644 index 0000000..00fdad9 --- /dev/null +++ b/rust/vendor/widestring/Cargo.toml @@ -0,0 +1,38 @@ +# 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 believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "widestring" +version = "0.4.3" +authors = ["Kathryn Long <squeeself@gmail.com>"] +description = "A wide string FFI library for converting to and from wide strings, such as those often used in Windows API or other FFI libraries. Both UTF-16 and UTF-32 types are provided." +readme = "README.md" +keywords = ["wide", "string", "win32", "utf-16", "utf-32"] +categories = ["text-processing", "encoding"] +license = "MIT/Apache-2.0" +repository = "https://github.com/starkat99/widestring-rs.git" +[dev-dependencies.winapi] +version = "0.3" +features = ["winbase"] + +[features] +alloc = [] +default = ["std"] +std = ["alloc"] +[badges.appveyor] +repository = "starkat99/widestring-rs" + +[badges.maintenance] +status = "passively-maintained" + +[badges.travis-ci] +repository = "starkat99/widestring-rs" diff --git a/rust/vendor/widestring/LICENSE-APACHE b/rust/vendor/widestring/LICENSE-APACHE new file mode 100644 index 0000000..1b22bef --- /dev/null +++ b/rust/vendor/widestring/LICENSE-APACHE @@ -0,0 +1,201 @@ + 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 + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License.
\ No newline at end of file diff --git a/rust/vendor/widestring/LICENSE-MIT b/rust/vendor/widestring/LICENSE-MIT new file mode 100644 index 0000000..8fbcc58 --- /dev/null +++ b/rust/vendor/widestring/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2016 Kathryn Long + +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.
\ No newline at end of file diff --git a/rust/vendor/widestring/README.md b/rust/vendor/widestring/README.md new file mode 100644 index 0000000..c9dac5b --- /dev/null +++ b/rust/vendor/widestring/README.md @@ -0,0 +1,37 @@ +# widestring +[![Crates.io](https://img.shields.io/crates/v/widestring.svg)](https://crates.io/crates/widestring/) [![docs.rs](https://docs.rs/widestring/badge.svg)](https://docs.rs/widestring/) [![Build status](https://ci.appveyor.com/api/projects/status/97pmbv6kk79bicww?svg=true)](https://ci.appveyor.com/project/starkat99/widestring-rs) [![Build Status](https://travis-ci.org/starkat99/widestring-rs.svg?branch=master)](https://travis-ci.org/starkat99/widestring-rs) + +A wide string Rust FFI library for converting to and from wide strings, such as +those often used in Windows API or other FFI libaries. Both UTF-16 and UTF-32 types are provided, including support for malformed encoding. + +## Documentation + +- [Crate API Reference](https://docs.rs/widestring/) +- [Latest Changes](CHANGELOG.md) + +### Optional Features + +- **`alloc`** - Enabled by default. Enable use of the [`alloc`](https://doc.rust-lang.org/alloc/) + crate when not using the `std` library. + + This enables the `U16String`, `U32String`, `U16CString`, `U32CString` types and alises. + +- **`std`** - Enabled by default. Enable features that depend on the Rust `std` library, including + everything in the `alloc` feature. + +## License + +This library is distributed under the terms of either of: + +* MIT license ([LICENSE-MIT](LICENSE-MIT) or +[http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT)) +* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or +[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)) + +at your option. + +### Contributing + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the +work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any +additional terms or conditions.
\ No newline at end of file diff --git a/rust/vendor/widestring/appveyor.yml b/rust/vendor/widestring/appveyor.yml new file mode 100644 index 0000000..8f69287 --- /dev/null +++ b/rust/vendor/widestring/appveyor.yml @@ -0,0 +1,117 @@ +# Appveyor configuration template for Rust using rustup for Rust installation +# https://github.com/starkat99/appveyor-rust + +## Operating System (VM environment) ## + +# Rust needs at least Visual Studio 2013 Appveyor OS for MSVC targets. +os: Visual Studio 2017 + +## Build Matrix ## + +# This configuration will setup a build for each channel & target combination (12 windows +# combinations in all). +# +# There are 3 channels: stable, beta, and nightly. +# +# Alternatively, the full version may be specified for the channel to build using that specific +# version (e.g. channel: 1.5.0) +# +# The values for target are the set of windows Rust build targets. Each value is of the form +# +# ARCH-pc-windows-TOOLCHAIN +# +# Where ARCH is the target architecture, either x86_64 or i686, and TOOLCHAIN is the linker +# toolchain to use, either msvc or gnu. See https://www.rust-lang.org/downloads.html#win-foot for +# a description of the toolchain differences. +# See https://github.com/rust-lang-nursery/rustup.rs/#toolchain-specification for description of +# toolchains and host triples. +# +# Comment out channel/target combos you do not wish to build in CI. +# +# You may use the `cargoflags` and `RUSTFLAGS` variables to set additional flags for cargo commands +# and rustc, respectively. For instance, you can uncomment the cargoflags lines in the nightly +# channels to enable unstable features when building for nightly. Or you could add additional +# matrix entries to test different combinations of features. +environment: + matrix: + +### MSVC Toolchains ### + + # Stable 64-bit MSVC + - channel: stable + target: x86_64-pc-windows-msvc + # Stable 32-bit MSVC + - channel: stable + target: i686-pc-windows-msvc + # Beta 64-bit MSVC + - channel: beta + target: x86_64-pc-windows-msvc + # Beta 32-bit MSVC + - channel: beta + target: i686-pc-windows-msvc + # Nightly 64-bit MSVC + - channel: nightly + target: x86_64-pc-windows-msvc + # Nightly 32-bit MSVC + - channel: nightly + target: i686-pc-windows-msvc + +### GNU Toolchains ### + + # Stable 64-bit GNU + - channel: stable + target: x86_64-pc-windows-gnu + # Stable 32-bit GNU + - channel: stable + target: i686-pc-windows-gnu + # Beta 64-bit GNU + - channel: beta + target: x86_64-pc-windows-gnu + # Beta 32-bit GNU + - channel: beta + target: i686-pc-windows-gnu + # Nightly 64-bit GNU + - channel: nightly + target: x86_64-pc-windows-gnu + # Nightly 32-bit GNU + - channel: nightly + target: i686-pc-windows-gnu + +### Allowed failures ### + +# See Appveyor documentation for specific details. In short, place any channel or targets you wish +# to allow build failures on (usually nightly at least is a wise choice). This will prevent a build +# or test failure in the matching channels/targets from failing the entire build. +#matrix: +# allow_failures: +# - channel: nightly + +# If you only care about stable channel build failures, uncomment the following line: + #- channel: beta + +## Install Script ## + +# This is the most important part of the Appveyor configuration. This installs the version of Rust +# specified by the 'channel' and 'target' environment variables from the build matrix. This uses +# rustup to install Rust. +# +# For simple configurations, instead of using the build matrix, you can simply set the +# default-toolchain and default-host manually here. +install: + - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe + - rustup-init -yv --default-toolchain %channel% --default-host %target% + - set PATH=%PATH%;%USERPROFILE%\.cargo\bin + - rustc -vV + - cargo -vV + +## Build Script ## + +# 'cargo test' takes care of building for us, so disable Appveyor's build stage. This prevents +# the "directory does not contain a project or solution file" error. +build: false + +# Uses 'cargo test' to run tests and build. Alternatively, the project may call compiled programs +#directly or perform other testing commands. Rust will automatically be placed in the PATH +# environment variable. +test_script: + - cargo test --verbose diff --git a/rust/vendor/widestring/src/lib.rs b/rust/vendor/widestring/src/lib.rs new file mode 100644 index 0000000..d62fd98 --- /dev/null +++ b/rust/vendor/widestring/src/lib.rs @@ -0,0 +1,238 @@ +//! A wide string FFI module for converting to and from wide string variants. +//! +//! This module provides multiple types of wide strings: `U16String`, `U16CString`, `U32String`, +//! and `U32CString`. These types are backed by two generic implementations parameterized by +//! element size: `UString<C>` and `UCString<C>`. The `UCString` types are analogous to the +//! standard `CString` FFI type, while the `UString` types are analogous to `OsString`. Otherwise, +//! `U16` and `U32` types differ only in character width and encoding methods. +//! +//! For `U16String` and `U32String`, no guarantees are made about the underlying string data; they +//! are simply a sequence of UTF-16 *code units* or UTF-32 code points, both of which may be +//! ill-formed or contain nul values. `U16CString` and `U32CString`, on the other hand, are aware +//! of nul values and are guaranteed to be terminated with a nul value (unless unchecked methods +//! are used to construct the strings). Because `U16CString` and `U32CString` are C-style, +//! nul-terminated strings, they will have no interior nul values. All four string types may still +//! have unpaired UTF-16 surrogates or invalid UTF-32 code points; ill-formed data is preserved +//! until conversion to a basic Rust `String`. +//! +//! Use `U16String` or `U32String` when you simply need to pass-through strings, or when you know +//! or don't care if you're not dealing with a nul-terminated string, such as when string lengths +//! are provided and you are only reading strings from FFI, not writing them out to a FFI. +//! +//! Use `U16CString` or `U32CString` when you must properly handle nul values, and must deal with +//! nul-terminated C-style wide strings, such as when you pass strings into FFI functions. +//! +//! # Relationship to other Rust Strings +//! +//! Standard Rust strings `String` and `str` are well-formed Unicode data encoded as UTF-8. The +//! standard strings provide proper handling of Unicode and ensure strong safety guarantees. +//! +//! `CString` and `CStr` are strings used for C FFI. They handle nul-terminated C-style strings. +//! However, they do not have a builtin encoding, and conversions between C-style and other Rust +//! strings must specifically encode and decode the strings, and handle possibly invalid encoding +//! data. They are safe to use only in passing string-like data back and forth from C APIs but do +//! not provide any other guarantees, so may not be well-formed. +//! +//! `OsString` and `OsStr` are also strings for use with FFI. Unlike `CString`, they do no special +//! handling of nul values, but instead have an OS-specified encoding. While, for example, on Linux +//! systems this is usually the UTF-8 encoding, this is not the case for every platform. The +//! encoding may not even be 8-bit: on Windows, `OsString` uses a malformed encoding sometimes +//! referred to as "WTF-8". In any case, like `CString`, `OsString` has no additional guarantees +//! and may not be well-formed. +//! +//! Due to the loss of safety of these other string types, conversion to standard Rust `String` is +//! lossy, and may require knowledge of the underlying encoding, including platform-specific +//! quirks. +//! +//! The wide strings in this crate are roughly based on the principles of the string types in +//! `std::ffi`, though there are differences. `U16String`, `U32String`, `U16Str`, and `U32Str` are +//! roughly similar in role to `OsString` and `OsStr`, while `U16CString`, `U32CString`, `U16CStr`, +//! and `U32CStr` are roughly similar in role to `CString` and `CStr`. Conversion to FFI string +//! types is generally very straight forward and safe, while conversion directly between standard +//! Rust `String` is a lossy conversion just as `OsString` is. +//! +//! `U16String` and `U16CString` are treated as though they use UTF-16 encoding, even if they may +//! contain unpaired surrogates. `U32String` and `U32CString` are treated as though they use UTF-32 +//! encoding, even if they may contain values outside the valid Unicode character range. +//! +//! # Remarks on UTF-16 Code Units +//! +//! *Code units* are the 16-bit units that comprise UTF-16 sequences. Code units +//! can specify Unicode code points either as single units or in *surrogate pairs*. Because every +//! code unit might be part of a surrogate pair, many regular string operations, including +//! indexing into a wide string, writing to a wide string, or even iterating a wide string should +//! be handled with care and are greatly discouraged. Some operations have safer alternatives +//! provided, such as Unicode code point iteration instead of code unit iteration. Always keep in +//! mind that the number of code units (`len()`) of a wide string is **not** equivalent to the +//! number of Unicode characters in the string, merely the length of the UTF-16 encoding sequence. +//! In fact, Unicode code points do not even have a one-to-one mapping with characters! +//! +//! UTF-32 simply encodes Unicode code points as-is in 32-bit values, but Unicode character code +//! points are reserved only for 21-bits. Again, Unicode code points do not have a one-to-one +//! mapping with the concept of a visual character glyph. +//! +//! # FFI with C/C++ `wchar_t` +//! +//! C/C++'s `wchar_t` (and C++'s corresponding `widestring`) varies in size depending on compiler +//! and platform. Typically, `wchar_t` is 16-bits on Windows and 32-bits on most Unix-based +//! platforms. For convenience when using `wchar_t`-based FFI's, type aliases for the corresponding +//! string types are provided: `WideString` aliases `U16String` on Windows or `U32String` +//! elsewhere, `WideCString` aliases `U16CString` or `U32CString`, etc. The `WideChar` alias +//! is also provided, aliasing `u16` or `u32`. +//! +//! When not interacting with a FFI using `wchar_t`, it is recommended to use the string types +//! directly rather than via the wide alias. +//! +//! This crate supports `no_std` when default features are disabled. The `std` and `alloc` features +//! (enabled by default) enable the `U16String`, `U32String`, `U16CString`, and `U32CString` types +//! and aliases. Other types do not require allocation and can be used in a `no_std` environment. +//! +//! # Examples +//! +//! The following example uses `U16String` to get Windows error messages, since `FormatMessageW` +//! returns a string length for us and we don't need to pass error messages into other FFI +//! functions so we don't need to worry about nul values. +//! +//! ```rust +//! # #[cfg(not(windows))] +//! # fn main() {} +//! # extern crate winapi; +//! # extern crate widestring; +//! # #[cfg(windows)] +//! # fn main() { +//! use winapi::um::winbase::{FormatMessageW, LocalFree, FORMAT_MESSAGE_FROM_SYSTEM, +//! FORMAT_MESSAGE_ALLOCATE_BUFFER, FORMAT_MESSAGE_IGNORE_INSERTS}; +//! use winapi::shared::ntdef::LPWSTR; +//! use winapi::shared::minwindef::HLOCAL; +//! use std::ptr; +//! use widestring::U16String; +//! # use winapi::shared::minwindef::DWORD; +//! # let error_code: DWORD = 0; +//! +//! let U16Str: U16String; +//! unsafe { +//! // First, get a string buffer from some windows api such as FormatMessageW... +//! let mut buffer: LPWSTR = ptr::null_mut(); +//! let strlen = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | +//! FORMAT_MESSAGE_ALLOCATE_BUFFER | +//! FORMAT_MESSAGE_IGNORE_INSERTS, +//! ptr::null(), +//! error_code, // error code from GetLastError() +//! 0, +//! (&mut buffer as *mut LPWSTR) as LPWSTR, +//! 0, +//! ptr::null_mut()); +//! +//! // Get the buffer as a wide string +//! U16Str = U16String::from_ptr(buffer, strlen as usize); +//! // Since U16String creates an owned copy, it's safe to free original buffer now +//! // If you didn't want an owned copy, you could use &U16Str. +//! LocalFree(buffer as HLOCAL); +//! } +//! // Convert to a regular Rust String and use it to your heart's desire! +//! let message = U16Str.to_string_lossy(); +//! # assert_eq!(message, "The operation completed successfully.\r\n"); +//! # } +//! ``` +//! +//! The following example is the functionally the same, only using `U16CString` instead. +//! +//! ```rust +//! # #[cfg(not(windows))] +//! # fn main() {} +//! # extern crate winapi; +//! # extern crate widestring; +//! # #[cfg(windows)] +//! # fn main() { +//! use winapi::um::winbase::{FormatMessageW, LocalFree, FORMAT_MESSAGE_FROM_SYSTEM, +//! FORMAT_MESSAGE_ALLOCATE_BUFFER, FORMAT_MESSAGE_IGNORE_INSERTS}; +//! use winapi::shared::ntdef::LPWSTR; +//! use winapi::shared::minwindef::HLOCAL; +//! use std::ptr; +//! use widestring::U16CString; +//! # use winapi::shared::minwindef::DWORD; +//! # let error_code: DWORD = 0; +//! +//! let U16Str: U16CString; +//! unsafe { +//! // First, get a string buffer from some windows api such as FormatMessageW... +//! let mut buffer: LPWSTR = ptr::null_mut(); +//! FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | +//! FORMAT_MESSAGE_ALLOCATE_BUFFER | +//! FORMAT_MESSAGE_IGNORE_INSERTS, +//! ptr::null(), +//! error_code, // error code from GetLastError() +//! 0, +//! (&mut buffer as *mut LPWSTR) as LPWSTR, +//! 0, +//! ptr::null_mut()); +//! +//! // Get the buffer as a wide string +//! U16Str = U16CString::from_ptr_str(buffer); +//! // Since U16CString creates an owned copy, it's safe to free original buffer now +//! // If you didn't want an owned copy, you could use &U16CStr. +//! LocalFree(buffer as HLOCAL); +//! } +//! // Convert to a regular Rust String and use it to your heart's desire! +//! let message = U16Str.to_string_lossy(); +//! # assert_eq!(message, "The operation completed successfully.\r\n"); +//! # } +//! ``` + +#![deny(future_incompatible)] +#![warn( + unused, + anonymous_parameters, + missing_docs, + missing_copy_implementations, + missing_debug_implementations, + trivial_casts, + trivial_numeric_casts +)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "alloc", not(feature = "std")))] +extern crate alloc; +#[cfg(feature = "std")] +extern crate core; + +use core::fmt::Debug; + +#[cfg(feature = "std")] +mod platform; +mod ucstr; +#[cfg(feature = "alloc")] +mod ucstring; +mod ustr; +#[cfg(feature = "alloc")] +mod ustring; + +pub use crate::ucstr::*; +#[cfg(feature = "alloc")] +pub use crate::ucstring::*; +pub use crate::ustr::*; +#[cfg(feature = "alloc")] +pub use crate::ustring::*; + +/// Marker trait for primitive types used to represent UTF character data. Should not be used +/// directly. +pub trait UChar: Debug + Sized + Copy + Ord + Eq { + /// NUL character value + const NUL: Self; +} + +impl UChar for u16 { + const NUL: u16 = 0; +} + +impl UChar for u32 { + const NUL: u32 = 0; +} + +#[cfg(not(windows))] +/// Alias for `u16` or `u32` depending on platform. Intended to match typical C `wchar_t` size on platform. +pub type WideChar = u32; + +#[cfg(windows)] +/// Alias for `u16` or `u32` depending on platform. Intended to match typical C `wchar_t` size on platform. +pub type WideChar = u16; diff --git a/rust/vendor/widestring/src/platform/mod.rs b/rust/vendor/widestring/src/platform/mod.rs new file mode 100644 index 0000000..b61cbb3 --- /dev/null +++ b/rust/vendor/widestring/src/platform/mod.rs @@ -0,0 +1,9 @@ +#[cfg(windows)] +mod windows; +#[cfg(windows)] +pub(crate) use self::windows::*; + +#[cfg(not(windows))] +mod other; +#[cfg(not(windows))] +pub(crate) use self::other::*; diff --git a/rust/vendor/widestring/src/platform/other.rs b/rust/vendor/widestring/src/platform/other.rs new file mode 100644 index 0000000..4cc6257 --- /dev/null +++ b/rust/vendor/widestring/src/platform/other.rs @@ -0,0 +1,9 @@ +use std::ffi::{OsStr, OsString}; + +pub(crate) fn os_to_wide(s: &OsStr) -> Vec<u16> { + s.to_string_lossy().encode_utf16().collect() +} + +pub(crate) fn os_from_wide(s: &[u16]) -> OsString { + OsString::from(String::from_utf16_lossy(s)) +} diff --git a/rust/vendor/widestring/src/platform/windows.rs b/rust/vendor/widestring/src/platform/windows.rs new file mode 100644 index 0000000..5ff0f12 --- /dev/null +++ b/rust/vendor/widestring/src/platform/windows.rs @@ -0,0 +1,11 @@ +#![cfg(windows)] +use std::ffi::{OsStr, OsString}; +use std::os::windows::ffi::{OsStrExt, OsStringExt}; + +pub(crate) fn os_to_wide(s: &OsStr) -> Vec<u16> { + s.encode_wide().collect() +} + +pub(crate) fn os_from_wide(s: &[u16]) -> OsString { + OsString::from_wide(s) +} diff --git a/rust/vendor/widestring/src/ucstr.rs b/rust/vendor/widestring/src/ucstr.rs new file mode 100644 index 0000000..5dbbf16 --- /dev/null +++ b/rust/vendor/widestring/src/ucstr.rs @@ -0,0 +1,538 @@ +use crate::{UChar, WideChar}; +use core::slice; + +#[cfg(all(feature = "alloc", not(feature = "std")))] +use alloc::{ + borrow::ToOwned, + boxed::Box, + string::{FromUtf16Error, String}, + vec::Vec, +}; +#[cfg(feature = "std")] +use std::{ + borrow::ToOwned, + boxed::Box, + string::{FromUtf16Error, String}, + vec::Vec, +}; + +/// An error returned from `UCString` and `UCStr` to indicate that a terminating nul value +/// was missing. +/// +/// The error optionally returns the ownership of the invalid vector whenever a vector was owned. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct MissingNulError<C> { + #[cfg(feature = "alloc")] + pub(crate) inner: Option<Vec<C>>, + #[cfg(not(feature = "alloc"))] + _p: core::marker::PhantomData<C>, +} + +impl<C: UChar> MissingNulError<C> { + #[cfg(feature = "alloc")] + fn empty() -> Self { + Self { inner: None } + } + + #[cfg(not(feature = "alloc"))] + fn empty() -> Self { + Self { + _p: core::marker::PhantomData, + } + } + + /// Consumes this error, returning the underlying vector of `u16` values which generated the + /// error in the first place. + #[cfg(feature = "alloc")] + pub fn into_vec(self) -> Option<Vec<C>> { + self.inner + } +} + +impl<C: UChar> core::fmt::Display for MissingNulError<C> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "missing terminating nul value") + } +} + +#[cfg(feature = "std")] +impl<C: UChar> std::error::Error for MissingNulError<C> { + fn description(&self) -> &str { + "missing terminating nul value" + } +} + +/// C-style wide string reference for `UCString`. +/// +/// `UCStr` is aware of nul values. Unless unchecked conversions are used, all `UCStr` +/// strings end with a nul-terminator in the underlying buffer and contain no internal nul values. +/// The strings may still contain invalid or ill-formed UTF-16 or UTF-32 data. These strings are +/// intended to be used with FFI functions such as Windows API that may require nul-terminated +/// strings. +/// +/// `UCStr` can be converted to and from many other string types, including `UString`, +/// `OsString`, and `String`, making proper Unicode FFI safe and easy. +/// +/// Please prefer using the type aliases `U16CStr` or `U32CStr` or `WideCStr` to using +/// this type directly. +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct UCStr<C: UChar> { + inner: [C], +} + +impl<C: UChar> UCStr<C> { + /// Coerces a value into a `UCStr`. + pub fn new<S: AsRef<UCStr<C>> + ?Sized>(s: &S) -> &Self { + s.as_ref() + } + + /// Constructs a `UStr` from a nul-terminated string pointer. + /// + /// This will scan for nul values beginning with `p`. The first nul value will be used as the + /// nul terminator for the string, similar to how libc string functions such as `strlen` work. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid or has a + /// nul terminator, and the function could scan past the underlying buffer. + /// + /// `p` must be non-null. + /// + /// # Panics + /// + /// This function panics if `p` is null. + /// + /// # Caveat + /// + /// The lifetime for the returned string is inferred from its usage. To prevent accidental + /// misuse, it's suggested to tie the lifetime to whichever source lifetime is safe in the + /// context, such as by providing a helper function taking the lifetime of a host value for the + /// string, or by explicit annotation. + pub unsafe fn from_ptr_str<'a>(p: *const C) -> &'a Self { + assert!(!p.is_null()); + let mut i: isize = 0; + while *p.offset(i) != UChar::NUL { + i += 1; + } + let ptr: *const [C] = slice::from_raw_parts(p, i as usize + 1); + &*(ptr as *const UCStr<C>) + } + + /// Constructs a `UStr` from a pointer and a length. + /// + /// The `len` argument is the number of elements, **not** the number of bytes, and does + /// **not** include the nul terminator of the string. Thus, a `len` of 0 is valid and means that + /// `p` is a pointer directly to the nul terminator of the string. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. + /// + /// `p` must be non-null, even for zero `len`. + /// + /// The interior values of the pointer are not scanned for nul. Any interior nul values will + /// result in an invalid `UCStr`. + /// + /// # Panics + /// + /// This function panics if `p` is null or if a nul value is not found at offset `len` of `p`. + /// Only pointers with a nul terminator are valid. + /// + /// # Caveat + /// + /// The lifetime for the returned string is inferred from its usage. To prevent accidental + /// misuse, it's suggested to tie the lifetime to whichever source lifetime is safe in the + /// context, such as by providing a helper function taking the lifetime of a host value for the + /// string, or by explicit annotation. + pub unsafe fn from_ptr_with_nul<'a>(p: *const C, len: usize) -> &'a Self { + assert!(*p.add(len) == UChar::NUL); + let ptr: *const [C] = slice::from_raw_parts(p, len + 1); + &*(ptr as *const UCStr<C>) + } + + /// Constructs a `UCStr` from a slice of values that has a nul terminator. + /// + /// The slice will be scanned for nul values. When a nul value is found, it is treated as the + /// terminator for the string, and the `UCStr` slice will be truncated to that nul. + /// + /// # Failure + /// + /// If there are no no nul values in the slice, an error is returned. + pub fn from_slice_with_nul(slice: &[C]) -> Result<&Self, MissingNulError<C>> { + match slice.iter().position(|x| *x == UChar::NUL) { + None => Err(MissingNulError::empty()), + Some(i) => Ok(unsafe { UCStr::from_slice_with_nul_unchecked(&slice[..i + 1]) }), + } + } + + /// Constructs a `UCStr` from a slice of values that has a nul terminator. No + /// checking for nul values is performed. + /// + /// # Safety + /// + /// This function is unsafe because it can lead to invalid `UCStr` values when the slice + /// is missing a terminating nul value or there are non-terminating interior nul values + /// in the slice. + pub unsafe fn from_slice_with_nul_unchecked(slice: &[C]) -> &Self { + let ptr: *const [C] = slice; + &*(ptr as *const UCStr<C>) + } + + /// Copies the wide string to an new owned `UString`. + #[cfg(feature = "alloc")] + pub fn to_ucstring(&self) -> crate::UCString<C> { + unsafe { crate::UCString::from_vec_with_nul_unchecked(self.inner.to_owned()) } + } + + /// Copies the wide string to a new owned `UString`. + /// + /// The `UString` will **not** have a nul terminator. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16CString; + /// let wcstr = U16CString::from_str("MyString").unwrap(); + /// // Convert U16CString to a U16String + /// let wstr = wcstr.to_ustring(); + /// + /// // U16CString will have a terminating nul + /// let wcvec = wcstr.into_vec_with_nul(); + /// assert_eq!(wcvec[wcvec.len()-1], 0); + /// // The resulting U16String will not have the terminating nul + /// let wvec = wstr.into_vec(); + /// assert_ne!(wvec[wvec.len()-1], 0); + /// ``` + /// + /// ```rust + /// use widestring::U32CString; + /// let wcstr = U32CString::from_str("MyString").unwrap(); + /// // Convert U32CString to a U32String + /// let wstr = wcstr.to_ustring(); + /// + /// // U32CString will have a terminating nul + /// let wcvec = wcstr.into_vec_with_nul(); + /// assert_eq!(wcvec[wcvec.len()-1], 0); + /// // The resulting U32String will not have the terminating nul + /// let wvec = wstr.into_vec(); + /// assert_ne!(wvec[wvec.len()-1], 0); + /// ``` + #[cfg(feature = "alloc")] + pub fn to_ustring(&self) -> crate::UString<C> { + crate::UString::from_vec(self.as_slice()) + } + + /// Converts to a slice of the wide string. + /// + /// The slice will **not** include the nul terminator. + pub fn as_slice(&self) -> &[C] { + &self.inner[..self.len()] + } + + /// Converts to a slice of the wide string, including the nul terminator. + pub fn as_slice_with_nul(&self) -> &[C] { + &self.inner + } + + /// Returns a raw pointer to the wide string. + /// + /// The pointer is valid only as long as the lifetime of this reference. + pub fn as_ptr(&self) -> *const C { + self.inner.as_ptr() + } + + /// Returns the length of the wide string as number of elements (**not** number of bytes) + /// **not** including nul terminator. + pub fn len(&self) -> usize { + self.inner.len() - 1 + } + + /// Returns whether this wide string contains no data (i.e. is only the nul terminator). + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Converts a `Box<UCStr>` into a `UCString` without copying or allocating. + /// + /// # Examples + /// + /// ``` + /// use widestring::U16CString; + /// + /// let v = vec![102u16, 111u16, 111u16]; // "foo" + /// let c_string = U16CString::new(v.clone()).unwrap(); + /// let boxed = c_string.into_boxed_ucstr(); + /// assert_eq!(boxed.into_ucstring(), U16CString::new(v).unwrap()); + /// ``` + /// + /// ``` + /// use widestring::U32CString; + /// + /// let v = vec![102u32, 111u32, 111u32]; // "foo" + /// let c_string = U32CString::new(v.clone()).unwrap(); + /// let boxed = c_string.into_boxed_ucstr(); + /// assert_eq!(boxed.into_ucstring(), U32CString::new(v).unwrap()); + /// ``` + #[cfg(feature = "alloc")] + pub fn into_ucstring(self: Box<Self>) -> crate::UCString<C> { + let raw = Box::into_raw(self) as *mut [C]; + crate::UCString { + inner: unsafe { Box::from_raw(raw) }, + } + } + + #[cfg(feature = "alloc")] + pub(crate) fn from_inner(slice: &[C]) -> &UCStr<C> { + let ptr: *const [C] = slice; + unsafe { &*(ptr as *const UCStr<C>) } + } +} + +impl UCStr<u16> { + /// Decodes a wide string to an owned `OsString`. + /// + /// This makes a string copy of the `U16CStr`. Since `U16CStr` makes no guarantees that it is + /// valid UTF-16, there is no guarantee that the resulting `OsString` will be valid data. The + /// `OsString` will **not** have a nul terminator. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16CString; + /// use std::ffi::OsString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U16CString::from_str(s).unwrap(); + /// // Create an OsString from the wide string + /// let osstr = wstr.to_os_string(); + /// + /// assert_eq!(osstr, OsString::from(s)); + /// ``` + #[cfg(feature = "std")] + pub fn to_os_string(&self) -> std::ffi::OsString { + crate::platform::os_from_wide(self.as_slice()) + } + + /// Copies the wide string to a `String` if it contains valid UTF-16 data. + /// + /// # Failures + /// + /// Returns an error if the string contains any invalid UTF-16 data. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U16CString::from_str(s).unwrap(); + /// // Create a regular string from the wide string + /// let s2 = wstr.to_string().unwrap(); + /// + /// assert_eq!(s2, s); + /// ``` + #[cfg(feature = "alloc")] + pub fn to_string(&self) -> Result<String, FromUtf16Error> { + String::from_utf16(self.as_slice()) + } + + /// Copies the wide string to a `String`. + /// + /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U16CString::from_str(s).unwrap(); + /// // Create a regular string from the wide string + /// let s2 = wstr.to_string_lossy(); + /// + /// assert_eq!(s2, s); + /// ``` + #[cfg(feature = "alloc")] + pub fn to_string_lossy(&self) -> String { + String::from_utf16_lossy(self.as_slice()) + } +} + +impl UCStr<u32> { + /// Constructs a `U32Str` from a `char` nul-terminated string pointer. + /// + /// This will scan for nul values beginning with `p`. The first nul value will be used as the + /// nul terminator for the string, similar to how libc string functions such as `strlen` work. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid or has a + /// nul terminator, and the function could scan past the underlying buffer. + /// + /// `p` must be non-null. + /// + /// # Panics + /// + /// This function panics if `p` is null. + /// + /// # Caveat + /// + /// The lifetime for the returned string is inferred from its usage. To prevent accidental + /// misuse, it's suggested to tie the lifetime to whichever source lifetime is safe in the + /// context, such as by providing a helper function taking the lifetime of a host value for the + /// string, or by explicit annotation. + pub unsafe fn from_char_ptr_str<'a>(p: *const char) -> &'a Self { + UCStr::from_ptr_str(p as *const u32) + } + + /// Constructs a `U32Str` from a `char` pointer and a length. + /// + /// The `len` argument is the number of `char` elements, **not** the number of bytes, and does + /// **not** include the nul terminator of the string. Thus, a `len` of 0 is valid and means that + /// `p` is a pointer directly to the nul terminator of the string. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. + /// + /// `p` must be non-null, even for zero `len`. + /// + /// The interior values of the pointer are not scanned for nul. Any interior nul values will + /// result in an invalid `U32CStr`. + /// + /// # Panics + /// + /// This function panics if `p` is null or if a nul value is not found at offset `len` of `p`. + /// Only pointers with a nul terminator are valid. + /// + /// # Caveat + /// + /// The lifetime for the returned string is inferred from its usage. To prevent accidental + /// misuse, it's suggested to tie the lifetime to whichever source lifetime is safe in the + /// context, such as by providing a helper function taking the lifetime of a host value for the + /// string, or by explicit annotation. + pub unsafe fn from_char_ptr_with_nul<'a>(p: *const char, len: usize) -> &'a Self { + UCStr::from_ptr_with_nul(p as *const u32, len) + } + + /// Constructs a `U32CStr` from a slice of `char` values that has a nul terminator. + /// + /// The slice will be scanned for nul values. When a nul value is found, it is treated as the + /// terminator for the string, and the `U32CStr` slice will be truncated to that nul. + /// + /// # Failure + /// + /// If there are no no nul values in `slice`, an error is returned. + pub fn from_char_slice_with_nul(slice: &[char]) -> Result<&Self, MissingNulError<u32>> { + let ptr: *const [char] = slice; + UCStr::from_slice_with_nul(unsafe { &*(ptr as *const [u32]) }) + } + + /// Constructs a `U32CStr` from a slice of `char` values that has a nul terminator. No + /// checking for nul values is performed. + /// + /// # Safety + /// + /// This function is unsafe because it can lead to invalid `U32CStr` values when `slice` + /// is missing a terminating nul value or there are non-terminating interior nul values + /// in the slice. + pub unsafe fn from_char_slice_with_nul_unchecked(slice: &[char]) -> &Self { + let ptr: *const [char] = slice; + UCStr::from_slice_with_nul_unchecked(&*(ptr as *const [u32])) + } + + /// Decodes a wide string to an owned `OsString`. + /// + /// This makes a string copy of the `U32CStr`. Since `U32CStr` makes no guarantees that it is + /// valid UTF-32, there is no guarantee that the resulting `OsString` will be valid data. The + /// `OsString` will **not** have a nul terminator. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32CString; + /// use std::ffi::OsString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U32CString::from_str(s).unwrap(); + /// // Create an OsString from the wide string + /// let osstr = wstr.to_os_string(); + /// + /// assert_eq!(osstr, OsString::from(s)); + /// ``` + #[cfg(feature = "std")] + pub fn to_os_string(&self) -> std::ffi::OsString { + self.to_ustring().to_os_string() + } + + /// Copies the wide string to a `String` if it contains valid UTF-32 data. + /// + /// # Failures + /// + /// Returns an error if the string contains any invalid UTF-32 data. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U32CString::from_str(s).unwrap(); + /// // Create a regular string from the wide string + /// let s2 = wstr.to_string().unwrap(); + /// + /// assert_eq!(s2, s); + /// ``` + #[cfg(feature = "alloc")] + pub fn to_string(&self) -> Result<String, crate::FromUtf32Error> { + self.to_ustring().to_string() + } + + /// Copies the wide string to a `String`. + /// + /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U32CString::from_str(s).unwrap(); + /// // Create a regular string from the wide string + /// let s2 = wstr.to_string_lossy(); + /// + /// assert_eq!(s2, s); + /// ``` + #[cfg(feature = "alloc")] + pub fn to_string_lossy(&self) -> String { + self.to_ustring().to_string_lossy() + } +} + +/// C-style wide string reference for `U16CString`. +/// +/// `U16CStr` is aware of nul values. Unless unchecked conversions are used, all `U16CStr` +/// strings end with a nul-terminator in the underlying buffer and contain no internal nul values. +/// The strings may still contain invalid or ill-formed UTF-16 data. These strings are intended to +/// be used with FFI functions such as Windows API that may require nul-terminated strings. +/// +/// `U16CStr` can be converted to and from many other string types, including `U16String`, +/// `OsString`, and `String`, making proper Unicode FFI safe and easy. +pub type U16CStr = UCStr<u16>; + +/// C-style wide string reference for `U32CString`. +/// +/// `U32CStr` is aware of nul values. Unless unchecked conversions are used, all `U32CStr` +/// strings end with a nul-terminator in the underlying buffer and contain no internal nul values. +/// The strings may still contain invalid or ill-formed UTF-32 data. These strings are intended to +/// be used with FFI functions such as Windows API that may require nul-terminated strings. +/// +/// `U32CStr` can be converted to and from many other string types, including `U32String`, +/// `OsString`, and `String`, making proper Unicode FFI safe and easy. +pub type U32CStr = UCStr<u32>; + +/// Alias for `U16CStr` or `U32CStr` depending on platform. Intended to match typical C `wchar_t` size on platform. +pub type WideCStr = UCStr<WideChar>; diff --git a/rust/vendor/widestring/src/ucstring.rs b/rust/vendor/widestring/src/ucstring.rs new file mode 100644 index 0000000..ddb7338 --- /dev/null +++ b/rust/vendor/widestring/src/ucstring.rs @@ -0,0 +1,1570 @@ +use crate::{MissingNulError, UCStr, UChar, UStr, UString, WideChar}; +use core::{ + borrow::Borrow, + mem, + mem::ManuallyDrop, + ops::{Deref, Index, RangeFull}, + ptr, slice, +}; + +#[cfg(all(feature = "alloc", not(feature = "std")))] +use alloc::{ + borrow::{Cow, ToOwned}, + boxed::Box, + vec::Vec, +}; +#[cfg(feature = "std")] +use std::{ + borrow::{Cow, ToOwned}, + boxed::Box, + vec::Vec, +}; + +/// An owned, mutable C-style "wide" string for FFI that is nul-aware and nul-terminated. +/// +/// `UCString` is aware of nul values. Unless unchecked conversions are used, all `UCString` +/// strings end with a nul-terminator in the underlying buffer and contain no internal nul values. +/// The strings may still contain invalid or ill-formed UTF-16 or UTF-32 data. These strings are +/// intended to be used with FFI functions such as Windows API that may require nul-terminated +/// strings. +/// +/// `UCString` can be converted to and from many other string types, including `UString`, +/// `OsString`, and `String`, making proper Unicode FFI safe and easy. +/// +/// Please prefer using the type aliases `U16CString` or `U32CString` or `WideCString` to using +/// this type directly. +/// +/// # Examples +/// +/// The following example constructs a `U16CString` and shows how to convert a `U16CString` to a +/// regular Rust `String`. +/// +/// ```rust +/// use widestring::U16CString; +/// let s = "Test"; +/// // Create a wide string from the rust string +/// let wstr = U16CString::from_str(s).unwrap(); +/// // Convert back to a rust string +/// let rust_str = wstr.to_string_lossy(); +/// assert_eq!(rust_str, "Test"); +/// ``` +/// +/// The same example using `U32CString`: +/// +/// ```rust +/// use widestring::U32CString; +/// let s = "Test"; +/// // Create a wide string from the rust string +/// let wstr = U32CString::from_str(s).unwrap(); +/// // Convert back to a rust string +/// let rust_str = wstr.to_string_lossy(); +/// assert_eq!(rust_str, "Test"); +/// ``` +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct UCString<C: UChar> { + pub(crate) inner: Box<[C]>, +} + +/// An error returned from `UCString` to indicate that an invalid nul value was found. +/// +/// The error indicates the position in the vector where the nul value was found, as well as +/// returning the ownership of the invalid vector. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct NulError<C: UChar>(usize, Vec<C>); + +impl<C: UChar> UCString<C> { + /// Constructs a `UCString` from a container of wide character data. + /// + /// This method will consume the provided data and use the underlying elements to construct a + /// new string. The data will be scanned for invalid nul values. + /// + /// # Failures + /// + /// This function will return an error if the data contains a nul value. + /// The returned error will contain the `Vec` as well as the position of the nul value. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16CString; + /// let v = vec![84u16, 104u16, 101u16]; // 'T' 'h' 'e' + /// # let cloned = v.clone(); + /// // Create a wide string from the vector + /// let wcstr = U16CString::new(v).unwrap(); + /// # assert_eq!(wcstr.into_vec(), cloned); + /// ``` + /// + /// ```rust + /// use widestring::U32CString; + /// let v = vec![84u32, 104u32, 101u32]; // 'T' 'h' 'e' + /// # let cloned = v.clone(); + /// // Create a wide string from the vector + /// let wcstr = U32CString::new(v).unwrap(); + /// # assert_eq!(wcstr.into_vec(), cloned); + /// ``` + /// + /// The following example demonstrates errors from nul values in a vector. + /// + /// ```rust + /// use widestring::U16CString; + /// let v = vec![84u16, 0u16, 104u16, 101u16]; // 'T' NUL 'h' 'e' + /// // Create a wide string from the vector + /// let res = U16CString::new(v); + /// assert!(res.is_err()); + /// assert_eq!(res.err().unwrap().nul_position(), 1); + /// ``` + /// + /// ```rust + /// use widestring::U32CString; + /// let v = vec![84u32, 0u32, 104u32, 101u32]; // 'T' NUL 'h' 'e' + /// // Create a wide string from the vector + /// let res = U32CString::new(v); + /// assert!(res.is_err()); + /// assert_eq!(res.err().unwrap().nul_position(), 1); + /// ``` + pub fn new(v: impl Into<Vec<C>>) -> Result<Self, NulError<C>> { + let v = v.into(); + // Check for nul vals + match v.iter().position(|&val| val == UChar::NUL) { + None => Ok(unsafe { UCString::from_vec_unchecked(v) }), + Some(pos) => Err(NulError(pos, v)), + } + } + + /// Constructs a `UCString` from a nul-terminated container of UTF-16 or UTF-32 data. + /// + /// This method will consume the provided data and use the underlying elements to construct a + /// new string. The string will be truncated at the first nul value in the string. + /// + /// # Failures + /// + /// This function will return an error if the data does not contain a nul to terminate the + /// string. The returned error will contain the consumed `Vec`. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16CString; + /// let v = vec![84u16, 104u16, 101u16, 0u16]; // 'T' 'h' 'e' NUL + /// # let cloned = v[..3].to_owned(); + /// // Create a wide string from the vector + /// let wcstr = U16CString::from_vec_with_nul(v).unwrap(); + /// # assert_eq!(wcstr.into_vec(), cloned); + /// ``` + /// + /// ```rust + /// use widestring::U32CString; + /// let v = vec![84u32, 104u32, 101u32, 0u32]; // 'T' 'h' 'e' NUL + /// # let cloned = v[..3].to_owned(); + /// // Create a wide string from the vector + /// let wcstr = U32CString::from_vec_with_nul(v).unwrap(); + /// # assert_eq!(wcstr.into_vec(), cloned); + /// ``` + /// + /// The following example demonstrates errors from missing nul values in a vector. + /// + /// ```rust + /// use widestring::U16CString; + /// let v = vec![84u16, 104u16, 101u16]; // 'T' 'h' 'e' + /// // Create a wide string from the vector + /// let res = U16CString::from_vec_with_nul(v); + /// assert!(res.is_err()); + /// ``` + /// + /// ```rust + /// use widestring::U32CString; + /// let v = vec![84u32, 104u32, 101u32]; // 'T' 'h' 'e' + /// // Create a wide string from the vector + /// let res = U32CString::from_vec_with_nul(v); + /// assert!(res.is_err()); + /// ``` + pub fn from_vec_with_nul(v: impl Into<Vec<C>>) -> Result<Self, MissingNulError<C>> { + let mut v = v.into(); + // Check for nul vals + match v.iter().position(|&val| val == UChar::NUL) { + None => Err(MissingNulError { inner: Some(v) }), + Some(pos) => { + v.truncate(pos + 1); + Ok(unsafe { UCString::from_vec_with_nul_unchecked(v) }) + } + } + } + + /// Creates a `UCString` from a vector without checking for interior nul values. + /// + /// A terminating nul value will be appended if the vector does not already have a terminating + /// nul. + /// + /// # Safety + /// + /// This method is equivalent to `new` except that no runtime assertion is made that `v` + /// contains no nul values. Providing a vector with nul values will result in an invalid + /// `UCString`. + pub unsafe fn from_vec_unchecked(v: impl Into<Vec<C>>) -> Self { + let mut v = v.into(); + match v.last() { + None => v.push(UChar::NUL), + Some(&c) if c != UChar::NUL => v.push(UChar::NUL), + Some(_) => (), + } + UCString::from_vec_with_nul_unchecked(v) + } + + /// Creates a `UCString` from a vector that should have a nul terminator, without checking + /// for any nul values. + /// + /// # Safety + /// + /// This method is equivalent to `from_vec_with_nul` except that no runtime assertion is made + /// that `v` contains no nul values. Providing a vector with interior nul values or without a + /// terminating nul value will result in an invalid `UCString`. + pub unsafe fn from_vec_with_nul_unchecked(v: impl Into<Vec<C>>) -> Self { + UCString { + inner: v.into().into_boxed_slice(), + } + } + + /// Constructs a `UCString` from anything that can be converted to a `UStr`. + /// + /// The string will be scanned for invalid nul values. + /// + /// # Failures + /// + /// This function will return an error if the data contains a nul value. + /// The returned error will contain a `Vec` as well as the position of the nul value. + pub fn from_ustr(s: impl AsRef<UStr<C>>) -> Result<Self, NulError<C>> { + UCString::new(s.as_ref().as_slice()) + } + + /// Constructs a `UCString` from anything that can be converted to a `UStr`, without + /// scanning for invalid nul values. + /// + /// # Safety + /// + /// This method is equivalent to `from_u16_str` except that no runtime assertion is made that + /// `s` contains no nul values. Providing a string with nul values will result in an invalid + /// `UCString`. + pub unsafe fn from_ustr_unchecked(s: impl AsRef<UStr<C>>) -> Self { + UCString::from_vec_unchecked(s.as_ref().as_slice()) + } + + /// Constructs a `UCString` from anything that can be converted to a `UStr` with a nul + /// terminator. + /// + /// The string will be truncated at the first nul value in the string. + /// + /// # Failures + /// + /// This function will return an error if the data does not contain a nul to terminate the + /// string. The returned error will contain the consumed `Vec`. + pub fn from_ustr_with_nul(s: impl AsRef<UStr<C>>) -> Result<Self, MissingNulError<C>> { + UCString::from_vec_with_nul(s.as_ref().as_slice()) + } + + /// Constructs a `UCString` from anything that can be converted to a `UStr` with a nul + /// terminator, without checking the string for any invalid interior nul values. + /// + /// # Safety + /// + /// This method is equivalent to `from_u16_str_with_nul` except that no runtime assertion is + /// made that `s` contains no nul values. Providing a vector with interior nul values or + /// without a terminating nul value will result in an invalid `UCString`. + pub unsafe fn from_ustr_with_nul_unchecked(s: impl AsRef<UStr<C>>) -> Self { + UCString::from_vec_with_nul_unchecked(s.as_ref().as_slice()) + } + + /// Constructs a new `UCString` copied from a nul-terminated string pointer. + /// + /// This will scan for nul values beginning with `p`. The first nul value will be used as the + /// nul terminator for the string, similar to how libc string functions such as `strlen` work. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid or has a + /// nul terminator, and the function could scan past the underlying buffer. + /// + /// `p` must be non-null. + /// + /// # Panics + /// + /// This function panics if `p` is null. + /// + /// # Caveat + /// + /// The lifetime for the returned string is inferred from its usage. To prevent accidental + /// misuse, it's suggested to tie the lifetime to whichever source lifetime is safe in the + /// context, such as by providing a helper function taking the lifetime of a host value for the + /// string, or by explicit annotation. + pub unsafe fn from_ptr_str(p: *const C) -> Self { + assert!(!p.is_null()); + let mut i: isize = 0; + while *p.offset(i) != UChar::NUL { + i += 1; + } + let slice = slice::from_raw_parts(p, i as usize + 1); + UCString::from_vec_with_nul_unchecked(slice) + } + + /// Converts to a `UCStr` reference. + pub fn as_ucstr(&self) -> &UCStr<C> { + self + } + + /// Converts the wide string into a `Vec` without a nul terminator, consuming the string in + /// the process. + /// + /// The resulting vector will **not** contain a nul-terminator, and will contain no other nul + /// values. + pub fn into_vec(self) -> Vec<C> { + let mut v = self.into_inner().into_vec(); + v.pop(); + v + } + + /// Converts the wide string into a `Vec`, consuming the string in the process. + /// + /// The resulting vector will contain a nul-terminator and no interior nul values. + pub fn into_vec_with_nul(self) -> Vec<C> { + self.into_inner().into_vec() + } + + /// Transfers ownership of the wide string to a C caller. + /// + /// # Safety + /// + /// The pointer must be returned to Rust and reconstituted using `from_raw` to be properly + /// deallocated. Specifically, one should _not_ use the standard C `free` function to + /// deallocate this string. + /// + /// Failure to call `from_raw` will lead to a memory leak. + pub fn into_raw(self) -> *mut C { + Box::into_raw(self.into_inner()) as *mut C + } + + /// Retakes ownership of a `UCString` that was transferred to C. + /// + /// # Safety + /// + /// This should only ever be called with a pointer that was earlier obtained by calling + /// `into_raw` on a `UCString`. Additionally, the length of the string will be recalculated + /// from the pointer. + pub unsafe fn from_raw(p: *mut C) -> Self { + assert!(!p.is_null()); + let mut i: isize = 0; + while *p.offset(i) != UChar::NUL { + i += 1; + } + let slice = slice::from_raw_parts_mut(p, i as usize + 1); + UCString { + inner: mem::transmute(slice), + } + } + + /// Converts this `UCString` into a boxed `UCStr`. + /// + /// # Examples + /// + /// ``` + /// use widestring::{U16CString, U16CStr}; + /// + /// let mut v = vec![102u16, 111u16, 111u16]; // "foo" + /// let c_string = U16CString::new(v.clone()).unwrap(); + /// let boxed = c_string.into_boxed_ucstr(); + /// v.push(0); + /// assert_eq!(&*boxed, U16CStr::from_slice_with_nul(&v).unwrap()); + /// ``` + /// + /// ``` + /// use widestring::{U32CString, U32CStr}; + /// + /// let mut v = vec![102u32, 111u32, 111u32]; // "foo" + /// let c_string = U32CString::new(v.clone()).unwrap(); + /// let boxed = c_string.into_boxed_ucstr(); + /// v.push(0); + /// assert_eq!(&*boxed, U32CStr::from_slice_with_nul(&v).unwrap()); + /// ``` + pub fn into_boxed_ucstr(self) -> Box<UCStr<C>> { + unsafe { Box::from_raw(Box::into_raw(self.into_inner()) as *mut UCStr<C>) } + } + + /// Bypass "move out of struct which implements [`Drop`] trait" restriction. + /// + /// [`Drop`]: ../ops/trait.Drop.html + fn into_inner(self) -> Box<[C]> { + unsafe { + let result = ptr::read(&self.inner); + mem::forget(self); + result + } + } +} + +impl UCString<u16> { + /// Constructs a `U16CString` from a `str`. + /// + /// The string will be scanned for invalid nul values. + /// + /// # Failures + /// + /// This function will return an error if the data contains a nul value. + /// The returned error will contain a `Vec<u16>` as well as the position of the nul value. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wcstr = U16CString::from_str(s).unwrap(); + /// # assert_eq!(wcstr.to_string_lossy(), s); + /// ``` + /// + /// The following example demonstrates errors from nul values in a vector. + /// + /// ```rust + /// use widestring::U16CString; + /// let s = "My\u{0}String"; + /// // Create a wide string from the string + /// let res = U16CString::from_str(s); + /// assert!(res.is_err()); + /// assert_eq!(res.err().unwrap().nul_position(), 2); + /// ``` + #[allow(clippy::should_implement_trait)] + pub fn from_str(s: impl AsRef<str>) -> Result<Self, NulError<u16>> { + let v: Vec<u16> = s.as_ref().encode_utf16().collect(); + UCString::new(v) + } + + /// Constructs a `U16CString` from a `str`, without checking for interior nul values. + /// + /// # Safety + /// + /// This method is equivalent to `from_str` except that no runtime assertion is made that `s` + /// contains no nul values. Providing a string with nul values will result in an invalid + /// `U16CString`. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wcstr = unsafe { U16CString::from_str_unchecked(s) }; + /// # assert_eq!(wcstr.to_string_lossy(), s); + /// ``` + pub unsafe fn from_str_unchecked(s: impl AsRef<str>) -> Self { + let v: Vec<u16> = s.as_ref().encode_utf16().collect(); + UCString::from_vec_unchecked(v) + } + + /// Constructs a `U16CString` from a `str` with a nul terminator. + /// + /// The string will be truncated at the first nul value in the string. + /// + /// # Failures + /// + /// This function will return an error if the data does not contain a nul to terminate the + /// string. The returned error will contain the consumed `Vec<u16>`. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16CString; + /// let s = "My\u{0}String"; + /// // Create a wide string from the string + /// let wcstr = U16CString::from_str_with_nul(s).unwrap(); + /// assert_eq!(wcstr.to_string_lossy(), "My"); + /// ``` + /// + /// The following example demonstrates errors from missing nul values in a vector. + /// + /// ```rust + /// use widestring::U16CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let res = U16CString::from_str_with_nul(s); + /// assert!(res.is_err()); + /// ``` + pub fn from_str_with_nul(s: impl AsRef<str>) -> Result<Self, MissingNulError<u16>> { + let v: Vec<u16> = s.as_ref().encode_utf16().collect(); + UCString::from_vec_with_nul(v) + } + + /// Constructs a `U16CString` from str `str` that should have a terminating nul, but without + /// checking for any nul values. + /// + /// # Safety + /// + /// This method is equivalent to `from_str_with_nul` except that no runtime assertion is made + /// that `s` contains no nul values. Providing a vector with interior nul values or without a + /// terminating nul value will result in an invalid `U16CString`. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16CString; + /// let s = "My String\u{0}"; + /// // Create a wide string from the string + /// let wcstr = unsafe { U16CString::from_str_with_nul_unchecked(s) }; + /// assert_eq!(wcstr.to_string_lossy(), "My String"); + /// ``` + pub unsafe fn from_str_with_nul_unchecked(s: impl AsRef<str>) -> Self { + let v: Vec<u16> = s.as_ref().encode_utf16().collect(); + UCString::from_vec_with_nul_unchecked(v) + } + + /// Constructs a new `U16CString` copied from a `u16` pointer and a length. + /// + /// The `len` argument is the number of `u16` elements, **not** the number of bytes. + /// + /// The string will be scanned for invalid nul values. + /// + /// # Failures + /// + /// This function will return an error if the data contains a nul value. + /// The returned error will contain a `Vec<u16>` as well as the position of the nul value. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. + /// + /// # Panics + /// + /// Panics if `len` is greater than 0 but `p` is a null pointer. + pub unsafe fn from_ptr(p: *const u16, len: usize) -> Result<Self, NulError<u16>> { + if len == 0 { + return Ok(UCString::default()); + } + assert!(!p.is_null()); + let slice = slice::from_raw_parts(p, len); + UCString::new(slice) + } + + /// Constructs a new `U16CString` copied from a `u16` pointer and a length. + /// + /// The `len` argument is the number of `u16` elements, **not** the number of bytes. + /// + /// The string will **not** be checked for invalid nul values. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. In addition, no checking for invalid nul values is performed, so if any elements + /// of `p` are a nul value, the resulting `U16CString` will be invalid. + /// + /// # Panics + /// + /// Panics if `len` is greater than 0 but `p` is a null pointer. + pub unsafe fn from_ptr_unchecked(p: *const u16, len: usize) -> Self { + if len == 0 { + return UCString::default(); + } + assert!(!p.is_null()); + let slice = slice::from_raw_parts(p, len); + UCString::from_vec_unchecked(slice) + } + + /// Constructs a new `U16String` copied from a `u16` pointer and a length. + /// + /// The `len` argument is the number of `u16` elements, **not** the number of bytes. + /// + /// The string will be truncated at the first nul value in the string. + /// + /// # Failures + /// + /// This function will return an error if the data does not contain a nul to terminate the + /// string. The returned error will contain the consumed `Vec<u16>`. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. + /// + /// # Panics + /// + /// Panics if `len` is greater than 0 but `p` is a null pointer. + pub unsafe fn from_ptr_with_nul( + p: *const u16, + len: usize, + ) -> Result<Self, MissingNulError<u16>> { + if len == 0 { + return Ok(UCString::default()); + } + assert!(!p.is_null()); + let slice = slice::from_raw_parts(p, len); + UCString::from_vec_with_nul(slice) + } + + /// Constructs a new `U16String` copied from a `u16` pointer and a length. + /// + /// The `len` argument is the number of `u16` elements, **not** the number of bytes. + /// + /// The data should end with a nul terminator, but no checking is done on whether the data + /// actually ends with a nul terminator, or if the data contains any interior nul values. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. In addition, no checking for nul values is performed, so if there data does not + /// end with a nul terminator, or if there are any interior nul values, the resulting + /// `U16CString` will be invalid. + /// + /// # Panics + /// + /// Panics if `len` is greater than 0 but `p` is a null pointer. + pub unsafe fn from_ptr_with_nul_unchecked(p: *const u16, len: usize) -> Self { + if len == 0 { + return UCString::default(); + } + assert!(!p.is_null()); + let slice = slice::from_raw_parts(p, len); + UCString::from_vec_with_nul_unchecked(slice) + } + + /// Constructs a `U16CString` from anything that can be converted to an `OsStr`. + /// + /// The string will be scanned for invalid nul values. + /// + /// # Failures + /// + /// This function will return an error if the data contains a nul value. + /// The returned error will contain a `Vec<u16>` as well as the position of the nul value. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wcstr = U16CString::from_os_str(s).unwrap(); + /// # assert_eq!(wcstr.to_string_lossy(), s); + /// ``` + /// + /// The following example demonstrates errors from nul values in a vector. + /// + /// ```rust + /// use widestring::U16CString; + /// let s = "My\u{0}String"; + /// // Create a wide string from the string + /// let res = U16CString::from_os_str(s); + /// assert!(res.is_err()); + /// assert_eq!(res.err().unwrap().nul_position(), 2); + /// ``` + #[cfg(feature = "std")] + pub fn from_os_str(s: impl AsRef<std::ffi::OsStr>) -> Result<Self, NulError<u16>> { + let v = crate::platform::os_to_wide(s.as_ref()); + UCString::new(v) + } + + /// Constructs a `U16CString` from anything that can be converted to an `OsStr`, without + /// checking for interior nul values. + /// + /// # Safety + /// + /// This method is equivalent to `from_os_str` except that no runtime assertion is made that + /// `s` contains no nul values. Providing a string with nul values will result in an invalid + /// `U16CString`. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wcstr = unsafe { U16CString::from_os_str_unchecked(s) }; + /// # assert_eq!(wcstr.to_string_lossy(), s); + /// ``` + #[cfg(feature = "std")] + pub unsafe fn from_os_str_unchecked(s: impl AsRef<std::ffi::OsStr>) -> Self { + let v = crate::platform::os_to_wide(s.as_ref()); + UCString::from_vec_unchecked(v) + } + + /// Constructs a `U16CString` from anything that can be converted to an `OsStr` with a nul + /// terminator. + /// + /// The string will be truncated at the first nul value in the string. + /// + /// # Failures + /// + /// This function will return an error if the data does not contain a nul to terminate the + /// string. The returned error will contain the consumed `Vec<u16>`. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16CString; + /// let s = "My\u{0}String"; + /// // Create a wide string from the string + /// let wcstr = U16CString::from_os_str_with_nul(s).unwrap(); + /// assert_eq!(wcstr.to_string_lossy(), "My"); + /// ``` + /// + /// The following example demonstrates errors from missing nul values in a vector. + /// + /// ```rust + /// use widestring::U16CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let res = U16CString::from_os_str_with_nul(s); + /// assert!(res.is_err()); + /// ``` + #[cfg(feature = "std")] + pub fn from_os_str_with_nul( + s: impl AsRef<std::ffi::OsStr>, + ) -> Result<Self, MissingNulError<u16>> { + let v = crate::platform::os_to_wide(s.as_ref()); + UCString::from_vec_with_nul(v) + } + + /// Constructs a `U16CString` from anything that can be converted to an `OsStr` that should + /// have a terminating nul, but without checking for any nul values. + /// + /// # Safety + /// + /// This method is equivalent to `from_os_str_with_nul` except that no runtime assertion is + /// made that `s` contains no nul values. Providing a vector with interior nul values or + /// without a terminating nul value will result in an invalid `U16CString`. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16CString; + /// let s = "My String\u{0}"; + /// // Create a wide string from the string + /// let wcstr = unsafe { U16CString::from_os_str_with_nul_unchecked(s) }; + /// assert_eq!(wcstr.to_string_lossy(), "My String"); + /// ``` + #[cfg(feature = "std")] + pub unsafe fn from_os_str_with_nul_unchecked(s: impl AsRef<std::ffi::OsStr>) -> Self { + let v = crate::platform::os_to_wide(s.as_ref()); + UCString::from_vec_with_nul_unchecked(v) + } +} + +impl UCString<u32> { + /// Constructs a `U32CString` from a container of wide character data. + /// + /// This method will consume the provided data and use the underlying elements to construct a + /// new string. The data will be scanned for invalid nul values. + /// + /// # Failures + /// + /// This function will return an error if the data contains a nul value. + /// The returned error will contain the `Vec<u32>` as well as the position of the nul value. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32CString; + /// let v: Vec<char> = "Test".chars().collect(); + /// # let cloned: Vec<u32> = v.iter().map(|&c| c as u32).collect(); + /// // Create a wide string from the vector + /// let wcstr = U32CString::from_chars(v).unwrap(); + /// # assert_eq!(wcstr.into_vec(), cloned); + /// ``` + /// + /// The following example demonstrates errors from nul values in a vector. + /// + /// ```rust + /// use widestring::U32CString; + /// let v: Vec<char> = "T\u{0}est".chars().collect(); + /// // Create a wide string from the vector + /// let res = U32CString::from_chars(v); + /// assert!(res.is_err()); + /// assert_eq!(res.err().unwrap().nul_position(), 1); + /// ``` + pub fn from_chars(v: impl Into<Vec<char>>) -> Result<Self, NulError<u32>> { + let mut chars = v.into(); + let v: Vec<u32> = unsafe { + let ptr = chars.as_mut_ptr() as *mut u32; + let len = chars.len(); + let cap = chars.capacity(); + ManuallyDrop::new(chars); + Vec::from_raw_parts(ptr, len, cap) + }; + UCString::new(v) + } + + /// Constructs a `U32CString` from a nul-terminated container of UTF-32 data. + /// + /// This method will consume the provided data and use the underlying elements to construct a + /// new string. The string will be truncated at the first nul value in the string. + /// + /// # Failures + /// + /// This function will return an error if the data does not contain a nul to terminate the + /// string. The returned error will contain the consumed `Vec<u32>`. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32CString; + /// let v: Vec<char> = "Test\u{0}".chars().collect(); + /// # let cloned: Vec<u32> = v[..4].iter().map(|&c| c as u32).collect(); + /// // Create a wide string from the vector + /// let wcstr = U32CString::from_chars_with_nul(v).unwrap(); + /// # assert_eq!(wcstr.into_vec(), cloned); + /// ``` + /// + /// The following example demonstrates errors from missing nul values in a vector. + /// + /// ```rust + /// use widestring::U32CString; + /// let v: Vec<char> = "Test".chars().collect(); + /// // Create a wide string from the vector + /// let res = U32CString::from_chars_with_nul(v); + /// assert!(res.is_err()); + /// ``` + pub fn from_chars_with_nul(v: impl Into<Vec<char>>) -> Result<Self, MissingNulError<u32>> { + let mut chars = v.into(); + let v: Vec<u32> = unsafe { + let ptr = chars.as_mut_ptr() as *mut u32; + let len = chars.len(); + let cap = chars.capacity(); + ManuallyDrop::new(chars); + Vec::from_raw_parts(ptr, len, cap) + }; + UCString::from_vec_with_nul(v) + } + + /// Creates a `U32CString` from a vector without checking for interior nul values. + /// + /// A terminating nul value will be appended if the vector does not already have a terminating + /// nul. + /// + /// # Safety + /// + /// This method is equivalent to `new` except that no runtime assertion is made that `v` + /// contains no nul values. Providing a vector with nul values will result in an invalid + /// `U32CString`. + pub unsafe fn from_chars_unchecked(v: impl Into<Vec<char>>) -> Self { + let mut chars = v.into(); + let v: Vec<u32> = { + let ptr = chars.as_mut_ptr() as *mut u32; + let len = chars.len(); + let cap = chars.capacity(); + ManuallyDrop::new(chars); + Vec::from_raw_parts(ptr, len, cap) + }; + UCString::from_vec_unchecked(v) + } + + /// Creates a `U32CString` from a vector that should have a nul terminator, without checking + /// for any nul values. + /// + /// # Safety + /// + /// This method is equivalent to `from_vec_with_nul` except that no runtime assertion is made + /// that `v` contains no nul values. Providing a vector with interior nul values or without a + /// terminating nul value will result in an invalid `U32CString`. + pub unsafe fn from_chars_with_nul_unchecked(v: impl Into<Vec<char>>) -> Self { + let mut chars = v.into(); + let v: Vec<u32> = { + let ptr = chars.as_mut_ptr() as *mut u32; + let len = chars.len(); + let cap = chars.capacity(); + ManuallyDrop::new(chars); + Vec::from_raw_parts(ptr, len, cap) + }; + UCString::from_vec_with_nul_unchecked(v) + } + + /// Constructs a `U32CString` from a `str`. + /// + /// The string will be scanned for invalid nul values. + /// + /// # Failures + /// + /// This function will return an error if the data contains a nul value. + /// The returned error will contain a `Vec<u32>` as well as the position of the nul value. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wcstr = U32CString::from_str(s).unwrap(); + /// # assert_eq!(wcstr.to_string_lossy(), s); + /// ``` + /// + /// The following example demonstrates errors from nul values in a vector. + /// + /// ```rust + /// use widestring::U32CString; + /// let s = "My\u{0}String"; + /// // Create a wide string from the string + /// let res = U32CString::from_str(s); + /// assert!(res.is_err()); + /// assert_eq!(res.err().unwrap().nul_position(), 2); + /// ``` + #[allow(clippy::should_implement_trait)] + pub fn from_str(s: impl AsRef<str>) -> Result<Self, NulError<u32>> { + let v: Vec<char> = s.as_ref().chars().collect(); + UCString::from_chars(v) + } + + /// Constructs a `U32CString` from a `str`, without checking for interior nul values. + /// + /// # Safety + /// + /// This method is equivalent to `from_str` except that no runtime assertion is made that `s` + /// contains no nul values. Providing a string with nul values will result in an invalid + /// `U32CString`. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wcstr = unsafe { U32CString::from_str_unchecked(s) }; + /// # assert_eq!(wcstr.to_string_lossy(), s); + /// ``` + pub unsafe fn from_str_unchecked(s: impl AsRef<str>) -> Self { + let v: Vec<char> = s.as_ref().chars().collect(); + UCString::from_chars_unchecked(v) + } + + /// Constructs a `U32CString` from a `str` with a nul terminator. + /// + /// The string will be truncated at the first nul value in the string. + /// + /// # Failures + /// + /// This function will return an error if the data does not contain a nul to terminate the + /// string. The returned error will contain the consumed `Vec<u32>`. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32CString; + /// let s = "My\u{0}String"; + /// // Create a wide string from the string + /// let wcstr = U32CString::from_str_with_nul(s).unwrap(); + /// assert_eq!(wcstr.to_string_lossy(), "My"); + /// ``` + /// + /// The following example demonstrates errors from missing nul values in a vector. + /// + /// ```rust + /// use widestring::U32CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let res = U32CString::from_str_with_nul(s); + /// assert!(res.is_err()); + /// ``` + pub fn from_str_with_nul(s: impl AsRef<str>) -> Result<Self, MissingNulError<u32>> { + let v: Vec<char> = s.as_ref().chars().collect(); + UCString::from_chars_with_nul(v) + } + + /// Constructs a `U32CString` from a `str` that should have a terminating nul, but without + /// checking for any nul values. + /// + /// # Safety + /// + /// This method is equivalent to `from_str_with_nul` except that no runtime assertion is made + /// that `s` contains no nul values. Providing a vector with interior nul values or without a + /// terminating nul value will result in an invalid `U32CString`. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32CString; + /// let s = "My String\u{0}"; + /// // Create a wide string from the string + /// let wcstr = unsafe { U32CString::from_str_with_nul_unchecked(s) }; + /// assert_eq!(wcstr.to_string_lossy(), "My String"); + /// ``` + pub unsafe fn from_str_with_nul_unchecked(s: impl AsRef<str>) -> Self { + let v: Vec<char> = s.as_ref().chars().collect(); + UCString::from_chars_with_nul_unchecked(v) + } + + /// Constructs a new `U32CString` copied from a `u32` pointer and a length. + /// + /// The `len` argument is the number of `u32` elements, **not** the number of bytes. + /// + /// The string will be scanned for invalid nul values. + /// + /// # Failures + /// + /// This function will return an error if the data contains a nul value. + /// The returned error will contain a `Vec<u32>` as well as the position of the nul value. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. + /// + /// # Panics + /// + /// Panics if `len` is greater than 0 but `p` is a null pointer. + pub unsafe fn from_ptr(p: *const u32, len: usize) -> Result<Self, NulError<u32>> { + if len == 0 { + return Ok(UCString::default()); + } + assert!(!p.is_null()); + let slice = slice::from_raw_parts(p, len); + UCString::new(slice) + } + + /// Constructs a new `U32CString` copied from a `u32` pointer and a length. + /// + /// The `len` argument is the number of `u32` elements, **not** the number of bytes. + /// + /// The string will **not** be checked for invalid nul values. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. In addition, no checking for invalid nul values is performed, so if any elements + /// of `p` are a nul value, the resulting `U16CString` will be invalid. + /// + /// # Panics + /// + /// Panics if `len` is greater than 0 but `p` is a null pointer. + pub unsafe fn from_ptr_unchecked(p: *const u32, len: usize) -> Self { + if len == 0 { + return UCString::default(); + } + assert!(!p.is_null()); + let slice = slice::from_raw_parts(p, len); + UCString::from_vec_unchecked(slice) + } + + /// Constructs a new `U32String` copied from a `u32` pointer and a length. + /// + /// The `len` argument is the number of `u32` elements, **not** the number of bytes. + /// + /// The string will be truncated at the first nul value in the string. + /// + /// # Failures + /// + /// This function will return an error if the data does not contain a nul to terminate the + /// string. The returned error will contain the consumed `Vec<u32>`. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. + /// + /// # Panics + /// + /// Panics if `len` is greater than 0 but `p` is a null pointer. + pub unsafe fn from_ptr_with_nul( + p: *const u32, + len: usize, + ) -> Result<Self, MissingNulError<u32>> { + if len == 0 { + return Ok(UCString::default()); + } + assert!(!p.is_null()); + let slice = slice::from_raw_parts(p, len); + UCString::from_vec_with_nul(slice) + } + + /// Constructs a new `U32String` copied from a `u32` pointer and a length. + /// + /// The `len` argument is the number of `u32` elements, **not** the number of bytes. + /// + /// The data should end with a nul terminator, but no checking is done on whether the data + /// actually ends with a nul terminator, or if the data contains any interior nul values. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. In addition, no checking for nul values is performed, so if there data does not + /// end with a nul terminator, or if there are any interior nul values, the resulting + /// `U32CString` will be invalid. + /// + /// # Panics + /// + /// Panics if `len` is greater than 0 but `p` is a null pointer. + pub unsafe fn from_ptr_with_nul_unchecked(p: *const u32, len: usize) -> Self { + if len == 0 { + return UCString::default(); + } + assert!(!p.is_null()); + let slice = slice::from_raw_parts(p, len); + UCString::from_vec_with_nul_unchecked(slice) + } + + /// Constructs a new `U32CString` copied from a `char` pointer and a length. + /// + /// The `len` argument is the number of `char` elements, **not** the number of bytes. + /// + /// The string will be scanned for invalid nul values. + /// + /// # Failures + /// + /// This function will return an error if the data contains a nul value. + /// The returned error will contain a `Vec<u32>` as well as the position of the nul value. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. + /// + /// # Panics + /// + /// Panics if `len` is greater than 0 but `p` is a null pointer. + pub unsafe fn from_char_ptr(p: *const char, len: usize) -> Result<Self, NulError<u32>> { + UCString::<u32>::from_ptr(p as *const u32, len) + } + + /// Constructs a new `U32CString` copied from a `char` pointer and a length. + /// + /// The `len` argument is the number of `char` elements, **not** the number of bytes. + /// + /// The string will **not** be checked for invalid nul values. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. In addition, no checking for invalid nul values is performed, so if any elements + /// of `p` are a nul value, the resulting `U32CString` will be invalid. + /// + /// # Panics + /// + /// Panics if `len` is greater than 0 but `p` is a null pointer. + pub unsafe fn from_char_ptr_unchecked(p: *const char, len: usize) -> Self { + UCString::<u32>::from_ptr_unchecked(p as *const u32, len) + } + + /// Constructs a new `U32String` copied from a `char` pointer and a length. + /// + /// The `len` argument is the number of `char` elements, **not** the number of bytes. + /// + /// The string will be truncated at the first nul value in the string. + /// + /// # Failures + /// + /// This function will return an error if the data does not contain a nul to terminate the + /// string. The returned error will contain the consumed `Vec<u32>`. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. + /// + /// # Panics + /// + /// Panics if `len` is greater than 0 but `p` is a null pointer. + pub unsafe fn from_char_ptr_with_nul( + p: *const char, + len: usize, + ) -> Result<Self, MissingNulError<u32>> { + UCString::<u32>::from_ptr_with_nul(p as *const u32, len) + } + + /// Constructs a new `U32String` copied from a `char` pointer and a length. + /// + /// The `len` argument is the number of `char` elements, **not** the number of bytes. + /// + /// The data should end with a nul terminator, but no checking is done on whether the data + /// actually ends with a nul terminator, or if the data contains any interior nul values. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. In addition, no checking for nul values is performed, so if there data does not + /// end with a nul terminator, or if there are any interior nul values, the resulting + /// `U32CString` will be invalid. + /// + /// # Panics + /// + /// Panics if `len` is greater than 0 but `p` is a null pointer. + pub unsafe fn from_char_ptr_with_nul_unchecked(p: *const char, len: usize) -> Self { + UCString::<u32>::from_ptr_with_nul_unchecked(p as *const u32, len) + } + + /// Constructs a `U32CString` from anything that can be converted to an `OsStr`. + /// + /// The string will be scanned for invalid nul values. + /// + /// # Failures + /// + /// This function will return an error if the data contains a nul value. + /// The returned error will contain a `Vec<u16>` as well as the position of the nul value. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wcstr = U32CString::from_os_str(s).unwrap(); + /// # assert_eq!(wcstr.to_string_lossy(), s); + /// ``` + /// + /// The following example demonstrates errors from nul values in a vector. + /// + /// ```rust + /// use widestring::U32CString; + /// let s = "My\u{0}String"; + /// // Create a wide string from the string + /// let res = U32CString::from_os_str(s); + /// assert!(res.is_err()); + /// assert_eq!(res.err().unwrap().nul_position(), 2); + /// ``` + #[cfg(feature = "std")] + pub fn from_os_str(s: impl AsRef<std::ffi::OsStr>) -> Result<Self, NulError<u32>> { + let v: Vec<char> = s.as_ref().to_string_lossy().chars().collect(); + UCString::from_chars(v) + } + + /// Constructs a `U32CString` from anything that can be converted to an `OsStr`, without + /// checking for interior nul values. + /// + /// # Safety + /// + /// This method is equivalent to `from_os_str` except that no runtime assertion is made that + /// `s` contains no nul values. Providing a string with nul values will result in an invalid + /// `U32CString`. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wcstr = unsafe { U32CString::from_os_str_unchecked(s) }; + /// # assert_eq!(wcstr.to_string_lossy(), s); + /// ``` + #[cfg(feature = "std")] + pub unsafe fn from_os_str_unchecked(s: impl AsRef<std::ffi::OsStr>) -> Self { + let v: Vec<char> = s.as_ref().to_string_lossy().chars().collect(); + UCString::from_chars_unchecked(v) + } + + /// Constructs a `U32CString` from anything that can be converted to an `OsStr` with a nul + /// terminator. + /// + /// The string will be truncated at the first nul value in the string. + /// + /// # Failures + /// + /// This function will return an error if the data does not contain a nul to terminate the + /// string. The returned error will contain the consumed `Vec<u16>`. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32CString; + /// let s = "My\u{0}String"; + /// // Create a wide string from the string + /// let wcstr = U32CString::from_os_str_with_nul(s).unwrap(); + /// assert_eq!(wcstr.to_string_lossy(), "My"); + /// ``` + /// + /// The following example demonstrates errors from missing nul values in a vector. + /// + /// ```rust + /// use widestring::U32CString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let res = U32CString::from_os_str_with_nul(s); + /// assert!(res.is_err()); + /// ``` + #[cfg(feature = "std")] + pub fn from_os_str_with_nul( + s: impl AsRef<std::ffi::OsStr>, + ) -> Result<Self, MissingNulError<u32>> { + let v: Vec<char> = s.as_ref().to_string_lossy().chars().collect(); + UCString::from_chars_with_nul(v) + } + + /// Constructs a `U32CString` from anything that can be converted to an `OsStr` that should + /// have a terminating nul, but without checking for any nul values. + /// + /// # Safety + /// + /// This method is equivalent to `from_os_str_with_nul` except that no runtime assertion is + /// made that `s` contains no nul values. Providing a vector with interior nul values or + /// without a terminating nul value will result in an invalid `U32CString`. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32CString; + /// let s = "My String\u{0}"; + /// // Create a wide string from the string + /// let wcstr = unsafe { U32CString::from_os_str_with_nul_unchecked(s) }; + /// assert_eq!(wcstr.to_string_lossy(), "My String"); + /// ``` + #[cfg(feature = "std")] + pub unsafe fn from_os_str_with_nul_unchecked(s: impl AsRef<std::ffi::OsStr>) -> Self { + let v: Vec<char> = s.as_ref().to_string_lossy().chars().collect(); + UCString::from_chars_with_nul_unchecked(v) + } +} + +impl<C: UChar> Into<Vec<C>> for UCString<C> { + fn into(self) -> Vec<C> { + self.into_vec() + } +} + +impl<'a> From<UCString<u16>> for Cow<'a, UCStr<u16>> { + fn from(s: UCString<u16>) -> Cow<'a, UCStr<u16>> { + Cow::Owned(s) + } +} + +impl<'a> From<UCString<u32>> for Cow<'a, UCStr<u32>> { + fn from(s: UCString<u32>) -> Cow<'a, UCStr<u32>> { + Cow::Owned(s) + } +} + +#[cfg(feature = "std")] +impl From<UCString<u16>> for std::ffi::OsString { + fn from(s: UCString<u16>) -> std::ffi::OsString { + s.to_os_string() + } +} + +#[cfg(feature = "std")] +impl From<UCString<u32>> for std::ffi::OsString { + fn from(s: UCString<u32>) -> std::ffi::OsString { + s.to_os_string() + } +} + +impl<C: UChar> From<UCString<C>> for UString<C> { + fn from(s: UCString<C>) -> Self { + s.to_ustring() + } +} + +impl<'a, C: UChar, T: ?Sized + AsRef<UCStr<C>>> From<&'a T> for UCString<C> { + fn from(s: &'a T) -> Self { + s.as_ref().to_ucstring() + } +} + +impl<C: UChar> Index<RangeFull> for UCString<C> { + type Output = UCStr<C>; + + #[inline] + fn index(&self, _index: RangeFull) -> &UCStr<C> { + UCStr::from_inner(&self.inner) + } +} + +impl<C: UChar> Deref for UCString<C> { + type Target = UCStr<C>; + + #[inline] + fn deref(&self) -> &UCStr<C> { + &self[..] + } +} + +impl<'a> Default for &'a UCStr<u16> { + fn default() -> Self { + const SLICE: &[u16] = &[UChar::NUL]; + unsafe { UCStr::from_slice_with_nul_unchecked(SLICE) } + } +} + +impl<'a> Default for &'a UCStr<u32> { + fn default() -> Self { + const SLICE: &[u32] = &[UChar::NUL]; + unsafe { UCStr::from_slice_with_nul_unchecked(SLICE) } + } +} + +impl Default for UCString<u16> { + fn default() -> Self { + let def: &UCStr<u16> = Default::default(); + def.to_ucstring() + } +} + +impl Default for UCString<u32> { + fn default() -> Self { + let def: &UCStr<u32> = Default::default(); + def.to_ucstring() + } +} + +// Turns this `U16CString` into an empty string to prevent +// memory unsafe code from working by accident. Inline +// to prevent LLVM from optimizing it away in debug builds. +impl<C: UChar> Drop for UCString<C> { + #[inline] + fn drop(&mut self) { + unsafe { + *self.inner.get_unchecked_mut(0) = UChar::NUL; + } + } +} + +impl<C: UChar> Borrow<UCStr<C>> for UCString<C> { + fn borrow(&self) -> &UCStr<C> { + &self[..] + } +} + +impl<C: UChar> ToOwned for UCStr<C> { + type Owned = UCString<C>; + fn to_owned(&self) -> UCString<C> { + self.to_ucstring() + } +} + +impl<'a> From<&'a UCStr<u16>> for Cow<'a, UCStr<u16>> { + fn from(s: &'a UCStr<u16>) -> Cow<'a, UCStr<u16>> { + Cow::Borrowed(s) + } +} + +impl<'a> From<&'a UCStr<u32>> for Cow<'a, UCStr<u32>> { + fn from(s: &'a UCStr<u32>) -> Cow<'a, UCStr<u32>> { + Cow::Borrowed(s) + } +} + +impl<C: UChar> AsRef<UCStr<C>> for UCStr<C> { + fn as_ref(&self) -> &Self { + self + } +} + +impl<C: UChar> AsRef<UCStr<C>> for UCString<C> { + fn as_ref(&self) -> &UCStr<C> { + self + } +} + +impl<C: UChar> AsRef<[C]> for UCStr<C> { + fn as_ref(&self) -> &[C] { + self.as_slice() + } +} + +impl<C: UChar> AsRef<[C]> for UCString<C> { + fn as_ref(&self) -> &[C] { + self.as_slice() + } +} + +impl<'a, C: UChar> From<&'a UCStr<C>> for Box<UCStr<C>> { + fn from(s: &'a UCStr<C>) -> Box<UCStr<C>> { + let boxed: Box<[C]> = Box::from(s.as_slice_with_nul()); + unsafe { Box::from_raw(Box::into_raw(boxed) as *mut UCStr<C>) } + } +} + +impl<C: UChar> From<Box<UCStr<C>>> for UCString<C> { + #[inline] + fn from(s: Box<UCStr<C>>) -> Self { + s.into_ucstring() + } +} + +impl<C: UChar> From<UCString<C>> for Box<UCStr<C>> { + #[inline] + fn from(s: UCString<C>) -> Box<UCStr<C>> { + s.into_boxed_ucstr() + } +} + +impl<C: UChar> Default for Box<UCStr<C>> { + fn default() -> Box<UCStr<C>> { + let boxed: Box<[C]> = Box::from([UChar::NUL]); + unsafe { Box::from_raw(Box::into_raw(boxed) as *mut UCStr<C>) } + } +} + +impl<C: UChar> NulError<C> { + /// Returns the position of the nul value in the slice that was provided to `U16CString`. + pub fn nul_position(&self) -> usize { + self.0 + } + + /// Consumes this error, returning the underlying vector of u16 values which generated the error + /// in the first place. + pub fn into_vec(self) -> Vec<C> { + self.1 + } +} + +impl<C: UChar> Into<Vec<C>> for NulError<C> { + fn into(self) -> Vec<C> { + self.into_vec() + } +} + +impl<C: UChar> core::fmt::Display for NulError<C> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "nul value found at position {}", self.0) + } +} + +#[cfg(feature = "std")] +impl<C: UChar> std::error::Error for NulError<C> { + fn description(&self) -> &str { + "nul value found" + } +} + +/// An owned, mutable C-style "wide" string for FFI that is nul-aware and nul-terminated. +/// +/// `U16CString` is aware of nul values. Unless unchecked conversions are used, all `U16CString` +/// strings end with a nul-terminator in the underlying buffer and contain no internal nul values. +/// The strings may still contain invalid or ill-formed UTF-16 data. These strings are intended to +/// be used with FFI functions such as Windows API that may require nul-terminated strings. +/// +/// `U16CString` can be converted to and from many other string types, including `U16String`, +/// `OsString`, and `String`, making proper Unicode FFI safe and easy. +/// +/// # Examples +/// +/// The following example constructs a `U16CString` and shows how to convert a `U16CString` to a +/// regular Rust `String`. +/// +/// ```rust +/// use widestring::U16CString; +/// let s = "Test"; +/// // Create a wide string from the rust string +/// let wstr = U16CString::from_str(s).unwrap(); +/// // Convert back to a rust string +/// let rust_str = wstr.to_string_lossy(); +/// assert_eq!(rust_str, "Test"); +/// ``` +pub type U16CString = UCString<u16>; + +/// An owned, mutable C-style wide string for FFI that is nul-aware and nul-terminated. +/// +/// `U32CString` is aware of nul values. Unless unchecked conversions are used, all `U32CString` +/// strings end with a nul-terminator in the underlying buffer and contain no internal nul values. +/// The strings may still contain invalid or ill-formed UTF-32 data. These strings are intended to +/// be used with FFI functions such as Windows API that may require nul-terminated strings. +/// +/// `U32CString` can be converted to and from many other string types, including `U32String`, +/// `OsString`, and `String`, making proper Unicode FFI safe and easy. +/// +/// # Examples +/// +/// The following example constructs a `U32CString` and shows how to convert a `U32CString` to a +/// regular Rust `String`. +/// +/// ```rust +/// use widestring::U32CString; +/// let s = "Test"; +/// // Create a wide string from the rust string +/// let wstr = U32CString::from_str(s).unwrap(); +/// // Convert back to a rust string +/// let rust_str = wstr.to_string_lossy(); +/// assert_eq!(rust_str, "Test"); +/// ``` +pub type U32CString = UCString<u32>; + +/// Alias for `U16String` or `U32String` depending on platform. Intended to match typical C `wchar_t` size on platform. +pub type WideCString = UCString<WideChar>; diff --git a/rust/vendor/widestring/src/ustr.rs b/rust/vendor/widestring/src/ustr.rs new file mode 100644 index 0000000..398b549 --- /dev/null +++ b/rust/vendor/widestring/src/ustr.rs @@ -0,0 +1,359 @@ +use crate::{UChar, WideChar}; +use core::{char, slice}; + +#[cfg(all(feature = "alloc", not(feature = "std")))] +use alloc::{ + boxed::Box, + string::{FromUtf16Error, String}, + vec::Vec, +}; +#[cfg(feature = "std")] +use std::{ + boxed::Box, + string::{FromUtf16Error, String}, + vec::Vec, +}; + +/// A possible error value when converting a String from a UTF-32 byte slice. +/// +/// This type is the error type for the `to_string` method on `U32Str`. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct FromUtf32Error(); + +impl core::fmt::Display for FromUtf32Error { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "error converting from UTF-32 to UTF-8") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for FromUtf32Error { + fn description(&self) -> &str { + "error converting from UTF-32 to UTF-8" + } +} + +/// String slice reference for `U16String`. +/// +/// `UStr` is to `UString` as `str` is to `String`. +/// +/// `UStr` is not aware of nul values. Strings may or may not be nul-terminated, and may +/// contain invalid and ill-formed UTF-16 or UTF-32 data. These strings are intended to be used +/// with FFI functions that directly use string length, where the strings are known to have proper +/// nul-termination already, or where strings are merely being passed through without modification. +/// +/// `UCStr` should be used instead of nul-aware strings are required. +/// +/// `UStr` can be converted to many other string types, including `OsString` and `String`, making +/// proper Unicode FFI safe and easy. +/// +/// Please prefer using the type aliases `U16Str` or `U32Str` or `WideStr` to using this type +/// directly. +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct UStr<C: UChar> { + pub(crate) inner: [C], +} + +impl<C: UChar> UStr<C> { + /// Coerces a value into a `UStr`. + pub fn new<S: AsRef<Self> + ?Sized>(s: &S) -> &Self { + s.as_ref() + } + + /// Constructs a `UStr` from a pointer and a length. + /// + /// The `len` argument is the number of elements, **not** the number of bytes. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. + /// + /// # Panics + /// + /// This function panics if `p` is null. + /// + /// # Caveat + /// + /// The lifetime for the returned string is inferred from its usage. To prevent accidental + /// misuse, it's suggested to tie the lifetime to whichever source lifetime is safe in the + /// context, such as by providing a helper function taking the lifetime of a host value for the + /// string, or by explicit annotation. + pub unsafe fn from_ptr<'a>(p: *const C, len: usize) -> &'a Self { + assert!(!p.is_null()); + let slice: *const [C] = slice::from_raw_parts(p, len); + &*(slice as *const UStr<C>) + } + + /// Constructs a `UStr` from a slice of code points. + /// + /// No checks are performed on the slice. + pub fn from_slice(slice: &[C]) -> &Self { + let ptr: *const [C] = slice; + unsafe { &*(ptr as *const UStr<C>) } + } + + /// Copies the wide string to a new owned `UString`. + #[cfg(feature = "alloc")] + pub fn to_ustring(&self) -> crate::UString<C> { + crate::UString::from_vec(&self.inner) + } + + /// Converts to a slice of the wide string. + pub fn as_slice(&self) -> &[C] { + &self.inner + } + + /// Returns a raw pointer to the wide string. + /// + /// The pointer is valid only as long as the lifetime of this reference. + pub fn as_ptr(&self) -> *const C { + self.inner.as_ptr() + } + + /// Returns the length of the wide string as number of elements (**not** number of bytes). + pub fn len(&self) -> usize { + self.inner.len() + } + + /// Returns whether this wide string contains no data. + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + + /// Converts a `Box<UStr>` into a `UString` without copying or allocating. + #[cfg(feature = "alloc")] + pub fn into_ustring(self: Box<Self>) -> crate::UString<C> { + let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut [C]) }; + crate::UString { + inner: boxed.into_vec(), + } + } +} + +impl UStr<u16> { + /// Decodes a wide string to an owned `OsString`. + /// + /// This makes a string copy of the `U16Str`. Since `U16Str` makes no guarantees that it is + /// valid UTF-16, there is no guarantee that the resulting `OsString` will be valid data. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16String; + /// use std::ffi::OsString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U16String::from_str(s); + /// // Create an OsString from the wide string + /// let osstr = wstr.to_os_string(); + /// + /// assert_eq!(osstr, OsString::from(s)); + /// ``` + #[cfg(feature = "std")] + pub fn to_os_string(&self) -> std::ffi::OsString { + crate::platform::os_from_wide(&self.inner) + } + + /// Copies the wide string to a `String` if it contains valid UTF-16 data. + /// + /// # Failures + /// + /// Returns an error if the string contains any invalid UTF-16 data. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16String; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U16String::from_str(s); + /// // Create a regular string from the wide string + /// let s2 = wstr.to_string().unwrap(); + /// + /// assert_eq!(s2, s); + /// ``` + #[cfg(feature = "alloc")] + pub fn to_string(&self) -> Result<String, FromUtf16Error> { + String::from_utf16(&self.inner) + } + + /// Copies the wide string to a `String`. + /// + /// Any non-Unicode sequences are replaced with *U+FFFD REPLACEMENT CHARACTER*. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16String; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U16String::from_str(s); + /// // Create a regular string from the wide string + /// let lossy = wstr.to_string_lossy(); + /// + /// assert_eq!(lossy, s); + /// ``` + #[cfg(feature = "alloc")] + pub fn to_string_lossy(&self) -> String { + String::from_utf16_lossy(&self.inner) + } +} + +impl UStr<u32> { + /// Constructs a `U32Str` from a `char` pointer and a length. + /// + /// The `len` argument is the number of `char` elements, **not** the number of bytes. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. + /// + /// # Panics + /// + /// This function panics if `p` is null. + /// + /// # Caveat + /// + /// The lifetime for the returned string is inferred from its usage. To prevent accidental + /// misuse, it's suggested to tie the lifetime to whichever source lifetime is safe in the + /// context, such as by providing a helper function taking the lifetime of a host value for the + /// string, or by explicit annotation. + pub unsafe fn from_char_ptr<'a>(p: *const char, len: usize) -> &'a Self { + UStr::from_ptr(p as *const u32, len) + } + + /// Constructs a `U32Str` from a slice of `u32` code points. + /// + /// No checks are performed on the slice. + pub fn from_char_slice(slice: &[char]) -> &Self { + let ptr: *const [char] = slice; + unsafe { &*(ptr as *const UStr<u32>) } + } + + /// Decodes a wide string to an owned `OsString`. + /// + /// This makes a string copy of the `U32Str`. Since `U32Str` makes no guarantees that it is + /// valid UTF-32, there is no guarantee that the resulting `OsString` will be valid data. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32String; + /// use std::ffi::OsString; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U32String::from_str(s); + /// // Create an OsString from the wide string + /// let osstr = wstr.to_os_string(); + /// + /// assert_eq!(osstr, OsString::from(s)); + /// ``` + #[cfg(feature = "std")] + pub fn to_os_string(&self) -> std::ffi::OsString { + self.to_string_lossy().into() + } + + /// Copies the wide string to a `String` if it contains valid UTF-32 data. + /// + /// # Failures + /// + /// Returns an error if the string contains any invalid UTF-32 data. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32String; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U32String::from_str(s); + /// // Create a regular string from the wide string + /// let s2 = wstr.to_string().unwrap(); + /// + /// assert_eq!(s2, s); + /// ``` + #[cfg(feature = "alloc")] + pub fn to_string(&self) -> Result<String, FromUtf32Error> { + let chars: Vec<Option<char>> = self.inner.iter().map(|c| char::from_u32(*c)).collect(); + if chars.iter().any(|c| c.is_none()) { + return Err(FromUtf32Error()); + } + let size = chars.iter().filter_map(|o| o.map(|c| c.len_utf8())).sum(); + let mut vec = Vec::with_capacity(size); + unsafe { vec.set_len(size) }; + let mut i = 0; + for c in chars.iter().filter_map(|&o| o) { + c.encode_utf8(&mut vec[i..]); + i += c.len_utf8(); + } + Ok(unsafe { String::from_utf8_unchecked(vec) }) + } + + /// Copies the wide string to a `String`. + /// + /// Any non-Unicode sequences are replaced with *U+FFFD REPLACEMENT CHARACTER*. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32String; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U32String::from_str(s); + /// // Create a regular string from the wide string + /// let lossy = wstr.to_string_lossy(); + /// + /// assert_eq!(lossy, s); + /// ``` + #[cfg(feature = "alloc")] + pub fn to_string_lossy(&self) -> String { + let chars: Vec<char> = self + .inner + .iter() + .map(|&c| char::from_u32(c).unwrap_or(char::REPLACEMENT_CHARACTER)) + .collect(); + let size = chars.iter().map(|c| c.len_utf8()).sum(); + let mut vec = Vec::with_capacity(size); + unsafe { vec.set_len(size) }; + let mut i = 0; + for c in chars { + c.encode_utf8(&mut vec[i..]); + i += c.len_utf8(); + } + unsafe { String::from_utf8_unchecked(vec) } + } +} + +/// String slice reference for `U16String`. +/// +/// `U16Str` is to `U16String` as `str` is to `String`. +/// +/// `U16Str` is not aware of nul values. Strings may or may not be nul-terminated, and may +/// contain invalid and ill-formed UTF-16 data. These strings are intended to be used with +/// FFI functions that directly use string length, where the strings are known to have proper +/// nul-termination already, or where strings are merely being passed through without modification. +/// +/// `WideCStr` should be used instead of nul-aware strings are required. +/// +/// `U16Str` can be converted to many other string types, including `OsString` and `String`, making +/// proper Unicode FFI safe and easy. +pub type U16Str = UStr<u16>; + +/// String slice reference for `U32String`. +/// +/// `U32Str` is to `U32String` as `str` is to `String`. +/// +/// `U32Str` is not aware of nul values. Strings may or may not be nul-terminated, and may +/// contain invalid and ill-formed UTF-32 data. These strings are intended to be used with +/// FFI functions that directly use string length, where the strings are known to have proper +/// nul-termination already, or where strings are merely being passed through without modification. +/// +/// `WideCStr` should be used instead of nul-aware strings are required. +/// +/// `U32Str` can be converted to many other string types, including `OsString` and `String`, making +/// proper Unicode FFI safe and easy. +pub type U32Str = UStr<u32>; + +/// Alias for `U16Str` or `U32Str` depending on platform. Intended to match typical C `wchar_t` size on platform. +pub type WideStr = UStr<WideChar>; diff --git a/rust/vendor/widestring/src/ustring.rs b/rust/vendor/widestring/src/ustring.rs new file mode 100644 index 0000000..8faabe8 --- /dev/null +++ b/rust/vendor/widestring/src/ustring.rs @@ -0,0 +1,785 @@ +use crate::{UChar, UStr, WideChar}; +use core::{ + borrow::Borrow, + char, cmp, + mem::ManuallyDrop, + ops::{Deref, Index, RangeFull}, + slice, +}; + +#[cfg(all(feature = "alloc", not(feature = "std")))] +use alloc::{ + borrow::{Cow, ToOwned}, + boxed::Box, + string::String, + vec::Vec, +}; +#[cfg(feature = "std")] +use std::{ + borrow::{Cow, ToOwned}, + boxed::Box, + string::String, + vec::Vec, +}; + +/// An owned, mutable "wide" string for FFI that is **not** nul-aware. +/// +/// `UString` is not aware of nul values. Strings may or may not be nul-terminated, and may +/// contain invalid and ill-formed UTF-16 or UTF-32 data. These strings are intended to be used +/// with FFI functions that directly use string length, where the strings are known to have proper +/// nul-termination already, or where strings are merely being passed through without modification. +/// +/// `UCString` should be used instead if nul-aware strings are required. +/// +/// `UString` can be converted to and from many other standard Rust string types, including +/// `OsString` and `String`, making proper Unicode FFI safe and easy. +/// +/// Please prefer using the type aliases `U16String` or `U32String` or `WideString` to using this +/// type directly. +/// +/// # Examples +/// +/// The following example constructs a `U16String` and shows how to convert a `U16String` to a +/// regular Rust `String`. +/// +/// ```rust +/// use widestring::U16String; +/// let s = "Test"; +/// // Create a wide string from the rust string +/// let wstr = U16String::from_str(s); +/// // Convert back to a rust string +/// let rust_str = wstr.to_string_lossy(); +/// assert_eq!(rust_str, "Test"); +/// ``` +/// +/// The same example using `U32String` instead: +/// +/// ```rust +/// use widestring::U32String; +/// let s = "Test"; +/// // Create a wide string from the rust string +/// let wstr = U32String::from_str(s); +/// // Convert back to a rust string +/// let rust_str = wstr.to_string_lossy(); +/// assert_eq!(rust_str, "Test"); +/// ``` +#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct UString<C: UChar> { + pub(crate) inner: Vec<C>, +} + +impl<C: UChar> UString<C> { + /// Constructs a new empty `UString`. + pub fn new() -> Self { + Self { inner: Vec::new() } + } + + /// Constructs a `UString` from a vector of possibly invalid or ill-formed UTF-16 or UTF-32 + /// data. + /// + /// No checks are made on the contents of the vector. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16String; + /// let v = vec![84u16, 104u16, 101u16]; // 'T' 'h' 'e' + /// # let cloned = v.clone(); + /// // Create a wide string from the vector + /// let wstr = U16String::from_vec(v); + /// # assert_eq!(wstr.into_vec(), cloned); + /// ``` + /// + /// ```rust + /// use widestring::U32String; + /// let v = vec![84u32, 104u32, 101u32]; // 'T' 'h' 'e' + /// # let cloned = v.clone(); + /// // Create a wide string from the vector + /// let wstr = U32String::from_vec(v); + /// # assert_eq!(wstr.into_vec(), cloned); + /// ``` + pub fn from_vec(raw: impl Into<Vec<C>>) -> Self { + Self { inner: raw.into() } + } + + /// Constructs a `UString` from a pointer and a length. + /// + /// The `len` argument is the number of elements, **not** the number of bytes. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. + /// + /// # Panics + /// + /// Panics if `len` is greater than 0 but `p` is a null pointer. + pub unsafe fn from_ptr(p: *const C, len: usize) -> Self { + if len == 0 { + return Self::new(); + } + assert!(!p.is_null()); + let slice = slice::from_raw_parts(p, len); + Self::from_vec(slice) + } + + /// Creates a `UString` with the given capacity. + /// + /// The string will be able to hold exactly `capacity` partial code units without reallocating. + /// If `capacity` is set to 0, the string will not initially allocate. + pub fn with_capacity(capacity: usize) -> Self { + Self { + inner: Vec::with_capacity(capacity), + } + } + + /// Returns the capacity this `UString` can hold without reallocating. + pub fn capacity(&self) -> usize { + self.inner.capacity() + } + + /// Truncate the `UString` to zero length. + pub fn clear(&mut self) { + self.inner.clear() + } + + /// Reserves the capacity for at least `additional` more capacity to be inserted in the given + /// `UString`. + /// + /// More space may be reserved to avoid frequent allocations. + pub fn reserve(&mut self, additional: usize) { + self.inner.reserve(additional) + } + + /// Reserves the minimum capacity for exactly `additional` more capacity to be inserted in the + /// given `UString`. Does nothing if the capcity is already sufficient. + /// + /// Note that the allocator may give more space than is requested. Therefore capacity can not + /// be relied upon to be precisely minimal. Prefer `reserve` if future insertions are expected. + pub fn reserve_exact(&mut self, additional: usize) { + self.inner.reserve_exact(additional) + } + + /// Converts the wide string into a `Vec`, consuming the string in the process. + pub fn into_vec(self) -> Vec<C> { + self.inner + } + + /// Converts to a `UStr` reference. + pub fn as_ustr(&self) -> &UStr<C> { + self + } + + /// Extends the wide string with the given `&UStr`. + /// + /// No checks are performed on the strings. It is possible to end up nul values inside the + /// string, and it is up to the caller to determine if that is acceptable. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16String; + /// let s = "MyString"; + /// let mut wstr = U16String::from_str(s); + /// let cloned = wstr.clone(); + /// // Push the clone to the end, repeating the string twice. + /// wstr.push(cloned); + /// + /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString"); + /// ``` + /// + /// ```rust + /// use widestring::U32String; + /// let s = "MyString"; + /// let mut wstr = U32String::from_str(s); + /// let cloned = wstr.clone(); + /// // Push the clone to the end, repeating the string twice. + /// wstr.push(cloned); + /// + /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString"); + /// ``` + pub fn push(&mut self, s: impl AsRef<UStr<C>>) { + self.inner.extend_from_slice(&s.as_ref().inner) + } + + /// Extends the wide string with the given slice. + /// + /// No checks are performed on the strings. It is possible to end up nul values inside the + /// string, and it is up to the caller to determine if that is acceptable. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16String; + /// let s = "MyString"; + /// let mut wstr = U16String::from_str(s); + /// let cloned = wstr.clone(); + /// // Push the clone to the end, repeating the string twice. + /// wstr.push_slice(cloned); + /// + /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString"); + /// ``` + /// + /// ```rust + /// use widestring::U32String; + /// let s = "MyString"; + /// let mut wstr = U32String::from_str(s); + /// let cloned = wstr.clone(); + /// // Push the clone to the end, repeating the string twice. + /// wstr.push_slice(cloned); + /// + /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString"); + /// ``` + pub fn push_slice(&mut self, s: impl AsRef<[C]>) { + self.inner.extend_from_slice(&s.as_ref()) + } + + /// Shrinks the capacity of the `UString` to match its length. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16String; + /// + /// let mut s = U16String::from_str("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to_fit(); + /// assert_eq!(3, s.capacity()); + /// ``` + /// + /// ```rust + /// use widestring::U32String; + /// + /// let mut s = U32String::from_str("foo"); + /// + /// s.reserve(100); + /// assert!(s.capacity() >= 100); + /// + /// s.shrink_to_fit(); + /// assert_eq!(3, s.capacity()); + /// ``` + pub fn shrink_to_fit(&mut self) { + self.inner.shrink_to_fit(); + } + + /// Converts this `UString` into a boxed `UStr`. + /// + /// # Examples + /// + /// ``` + /// use widestring::{U16String, U16Str}; + /// + /// let s = U16String::from_str("hello"); + /// + /// let b: Box<U16Str> = s.into_boxed_ustr(); + /// ``` + /// + /// ``` + /// use widestring::{U32String, U32Str}; + /// + /// let s = U32String::from_str("hello"); + /// + /// let b: Box<U32Str> = s.into_boxed_ustr(); + /// ``` + pub fn into_boxed_ustr(self) -> Box<UStr<C>> { + let rw = Box::into_raw(self.inner.into_boxed_slice()) as *mut UStr<C>; + unsafe { Box::from_raw(rw) } + } +} + +impl UString<u16> { + /// Encodes a `U16String` copy from a `str`. + /// + /// This makes a wide string copy of the `str`. Since `str` will always be valid UTF-8, the + /// resulting `U16String` will also be valid UTF-16. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16String; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U16String::from_str(s); + /// + /// assert_eq!(wstr.to_string().unwrap(), s); + /// ``` + #[allow(clippy::should_implement_trait)] + pub fn from_str<S: AsRef<str> + ?Sized>(s: &S) -> Self { + Self { + inner: s.as_ref().encode_utf16().collect(), + } + } + + /// Encodes a `U16String` copy from an `OsStr`. + /// + /// This makes a wide string copy of the `OsStr`. Since `OsStr` makes no guarantees that it is + /// valid data, there is no guarantee that the resulting `U16String` will be valid UTF-16. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16String; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U16String::from_os_str(s); + /// + /// assert_eq!(wstr.to_string().unwrap(), s); + /// ``` + #[cfg(feature = "std")] + pub fn from_os_str<S: AsRef<std::ffi::OsStr> + ?Sized>(s: &S) -> Self { + Self { + inner: crate::platform::os_to_wide(s.as_ref()), + } + } + + /// Extends the string with the given `&str`. + /// + /// No checks are performed on the strings. It is possible to end up nul values inside the + /// string, and it is up to the caller to determine if that is acceptable. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16String; + /// let s = "MyString"; + /// let mut wstr = U16String::from_str(s); + /// // Push the original to the end, repeating the string twice. + /// wstr.push_str(s); + /// + /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString"); + /// ``` + pub fn push_str(&mut self, s: impl AsRef<str>) { + self.inner.extend(s.as_ref().encode_utf16()) + } + + /// Extends the string with the given `&OsStr`. + /// + /// No checks are performed on the strings. It is possible to end up nul values inside the + /// string, and it is up to the caller to determine if that is acceptable. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U16String; + /// let s = "MyString"; + /// let mut wstr = U16String::from_str(s); + /// // Push the original to the end, repeating the string twice. + /// wstr.push_os_str(s); + /// + /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString"); + /// ``` + #[cfg(feature = "std")] + pub fn push_os_str(&mut self, s: impl AsRef<std::ffi::OsStr>) { + self.inner.extend(crate::platform::os_to_wide(s.as_ref())) + } +} + +impl UString<u32> { + /// Constructs a `U32String` from a vector of UTF-32 data. + /// + /// No checks are made on the contents of the vector. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32String; + /// let v: Vec<char> = "Test".chars().collect(); + /// # let cloned: Vec<u32> = v.iter().map(|&c| c as u32).collect(); + /// // Create a wide string from the vector + /// let wstr = U32String::from_chars(v); + /// # assert_eq!(wstr.into_vec(), cloned); + /// ``` + pub fn from_chars(raw: impl Into<Vec<char>>) -> Self { + let mut chars = raw.into(); + UString { + inner: unsafe { + let ptr = chars.as_mut_ptr() as *mut u32; + let len = chars.len(); + let cap = chars.capacity(); + ManuallyDrop::new(chars); + Vec::from_raw_parts(ptr, len, cap) + }, + } + } + + /// Encodes a `U32String` copy from a `str`. + /// + /// This makes a wide string copy of the `str`. Since `str` will always be valid UTF-8, the + /// resulting `U32String` will also be valid UTF-32. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32String; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U32String::from_str(s); + /// + /// assert_eq!(wstr.to_string().unwrap(), s); + /// ``` + #[allow(clippy::should_implement_trait)] + pub fn from_str<S: AsRef<str> + ?Sized>(s: &S) -> Self { + let v: Vec<char> = s.as_ref().chars().collect(); + UString::from_chars(v) + } + + /// Encodes a `U32String` copy from an `OsStr`. + /// + /// This makes a wide string copy of the `OsStr`. Since `OsStr` makes no guarantees that it is + /// valid data, there is no guarantee that the resulting `U32String` will be valid UTF-32. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32String; + /// let s = "MyString"; + /// // Create a wide string from the string + /// let wstr = U32String::from_os_str(s); + /// + /// assert_eq!(wstr.to_string().unwrap(), s); + /// ``` + #[cfg(feature = "std")] + pub fn from_os_str<S: AsRef<std::ffi::OsStr> + ?Sized>(s: &S) -> Self { + let v: Vec<char> = s.as_ref().to_string_lossy().chars().collect(); + UString::from_chars(v) + } + + /// Constructs a `U32String` from a `char` pointer and a length. + /// + /// The `len` argument is the number of `char` elements, **not** the number of bytes. + /// + /// # Safety + /// + /// This function is unsafe as there is no guarantee that the given pointer is valid for `len` + /// elements. + /// + /// # Panics + /// + /// Panics if `len` is greater than 0 but `p` is a null pointer. + pub unsafe fn from_char_ptr(p: *const char, len: usize) -> Self { + UString::from_ptr(p as *const u32, len) + } + + /// Extends the string with the given `&str`. + /// + /// No checks are performed on the strings. It is possible to end up nul values inside the + /// string, and it is up to the caller to determine if that is acceptable. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32String; + /// let s = "MyString"; + /// let mut wstr = U32String::from_str(s); + /// // Push the original to the end, repeating the string twice. + /// wstr.push_str(s); + /// + /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString"); + /// ``` + pub fn push_str(&mut self, s: impl AsRef<str>) { + self.inner.extend(s.as_ref().chars().map(|c| c as u32)) + } + + /// Extends the string with the given `&OsStr`. + /// + /// No checks are performed on the strings. It is possible to end up nul values inside the + /// string, and it is up to the caller to determine if that is acceptable. + /// + /// # Examples + /// + /// ```rust + /// use widestring::U32String; + /// let s = "MyString"; + /// let mut wstr = U32String::from_str(s); + /// // Push the original to the end, repeating the string twice. + /// wstr.push_os_str(s); + /// + /// assert_eq!(wstr.to_string().unwrap(), "MyStringMyString"); + /// ``` + #[cfg(feature = "std")] + pub fn push_os_str(&mut self, s: impl AsRef<std::ffi::OsStr>) { + self.inner + .extend(s.as_ref().to_string_lossy().chars().map(|c| c as u32)) + } +} + +impl<C: UChar> Into<Vec<C>> for UString<C> { + fn into(self) -> Vec<C> { + self.into_vec() + } +} + +impl<'a> From<UString<u16>> for Cow<'a, UStr<u16>> { + fn from(s: UString<u16>) -> Self { + Cow::Owned(s) + } +} + +impl<'a> From<UString<u32>> for Cow<'a, UStr<u32>> { + fn from(s: UString<u32>) -> Self { + Cow::Owned(s) + } +} + +impl Into<UString<u16>> for Vec<u16> { + fn into(self) -> UString<u16> { + UString::from_vec(self) + } +} + +impl Into<UString<u32>> for Vec<u32> { + fn into(self) -> UString<u32> { + UString::from_vec(self) + } +} + +impl Into<UString<u32>> for Vec<char> { + fn into(self) -> UString<u32> { + UString::from_chars(self) + } +} + +impl From<String> for UString<u16> { + fn from(s: String) -> Self { + Self::from_str(&s) + } +} + +impl From<String> for UString<u32> { + fn from(s: String) -> Self { + Self::from_str(&s) + } +} + +#[cfg(feature = "std")] +impl From<std::ffi::OsString> for UString<u16> { + fn from(s: std::ffi::OsString) -> Self { + Self::from_os_str(&s) + } +} + +#[cfg(feature = "std")] +impl From<std::ffi::OsString> for UString<u32> { + fn from(s: std::ffi::OsString) -> Self { + Self::from_os_str(&s) + } +} + +#[cfg(feature = "std")] +impl From<UString<u16>> for std::ffi::OsString { + fn from(s: UString<u16>) -> Self { + s.to_os_string() + } +} + +#[cfg(feature = "std")] +impl From<UString<u32>> for std::ffi::OsString { + fn from(s: UString<u32>) -> Self { + s.to_os_string() + } +} + +impl<'a, C: UChar, T: ?Sized + AsRef<UStr<C>>> From<&'a T> for UString<C> { + fn from(s: &'a T) -> Self { + s.as_ref().to_ustring() + } +} + +impl<C: UChar> Index<RangeFull> for UString<C> { + type Output = UStr<C>; + + #[inline] + fn index(&self, _index: RangeFull) -> &UStr<C> { + UStr::from_slice(&self.inner) + } +} + +impl<C: UChar> Deref for UString<C> { + type Target = UStr<C>; + + #[inline] + fn deref(&self) -> &UStr<C> { + &self[..] + } +} + +impl<C: UChar> PartialEq<UStr<C>> for UString<C> { + #[inline] + fn eq(&self, other: &UStr<C>) -> bool { + self.as_ustr() == other + } +} + +impl<C: UChar> PartialOrd<UStr<C>> for UString<C> { + #[inline] + fn partial_cmp(&self, other: &UStr<C>) -> Option<cmp::Ordering> { + self.as_ustr().partial_cmp(other) + } +} + +impl<'a, C: UChar> PartialEq<&'a UStr<C>> for UString<C> { + #[inline] + fn eq(&self, other: &&'a UStr<C>) -> bool { + self.as_ustr() == *other + } +} + +impl<'a, C: UChar> PartialOrd<&'a UStr<C>> for UString<C> { + #[inline] + fn partial_cmp(&self, other: &&'a UStr<C>) -> Option<cmp::Ordering> { + self.as_ustr().partial_cmp(*other) + } +} + +impl<'a, C: UChar> PartialEq<Cow<'a, UStr<C>>> for UString<C> { + #[inline] + fn eq(&self, other: &Cow<'a, UStr<C>>) -> bool { + self.as_ustr() == other.as_ref() + } +} + +impl<'a, C: UChar> PartialOrd<Cow<'a, UStr<C>>> for UString<C> { + #[inline] + fn partial_cmp(&self, other: &Cow<'a, UStr<C>>) -> Option<cmp::Ordering> { + self.as_ustr().partial_cmp(other.as_ref()) + } +} + +impl<C: UChar> Borrow<UStr<C>> for UString<C> { + fn borrow(&self) -> &UStr<C> { + &self[..] + } +} + +impl<C: UChar> ToOwned for UStr<C> { + type Owned = UString<C>; + fn to_owned(&self) -> UString<C> { + self.to_ustring() + } +} + +impl<'a> From<&'a UStr<u16>> for Cow<'a, UStr<u16>> { + fn from(s: &'a UStr<u16>) -> Self { + Cow::Borrowed(s) + } +} + +impl<'a> From<&'a UStr<u32>> for Cow<'a, UStr<u32>> { + fn from(s: &'a UStr<u32>) -> Self { + Cow::Borrowed(s) + } +} + +impl<C: UChar> AsRef<UStr<C>> for UStr<C> { + fn as_ref(&self) -> &Self { + self + } +} + +impl<C: UChar> AsRef<UStr<C>> for UString<C> { + fn as_ref(&self) -> &UStr<C> { + self + } +} + +impl<C: UChar> AsRef<[C]> for UStr<C> { + fn as_ref(&self) -> &[C] { + self.as_slice() + } +} + +impl<C: UChar> AsRef<[C]> for UString<C> { + fn as_ref(&self) -> &[C] { + self.as_slice() + } +} + +impl<'a, C: UChar> From<&'a UStr<C>> for Box<UStr<C>> { + fn from(s: &'a UStr<C>) -> Self { + let boxed: Box<[C]> = Box::from(&s.inner); + let rw = Box::into_raw(boxed) as *mut UStr<C>; + unsafe { Box::from_raw(rw) } + } +} + +impl<C: UChar> From<Box<UStr<C>>> for UString<C> { + fn from(boxed: Box<UStr<C>>) -> Self { + boxed.into_ustring() + } +} + +impl<C: UChar> From<UString<C>> for Box<UStr<C>> { + fn from(s: UString<C>) -> Self { + s.into_boxed_ustr() + } +} + +impl<C: UChar> Default for Box<UStr<C>> { + fn default() -> Self { + let boxed: Box<[C]> = Box::from([]); + let rw = Box::into_raw(boxed) as *mut UStr<C>; + unsafe { Box::from_raw(rw) } + } +} + +/// An owned, mutable "wide" string for FFI that is **not** nul-aware. +/// +/// `U16String` is not aware of nul values. Strings may or may not be nul-terminated, and may +/// contain invalid and ill-formed UTF-16 data. These strings are intended to be used with +/// FFI functions that directly use string length, where the strings are known to have proper +/// nul-termination already, or where strings are merely being passed through without modification. +/// +/// `WideCString` should be used instead if nul-aware strings are required. +/// +/// `U16String` can be converted to and from many other standard Rust string types, including +/// `OsString` and `String`, making proper Unicode FFI safe and easy. +/// +/// # Examples +/// +/// The following example constructs a `U16String` and shows how to convert a `U16String` to a +/// regular Rust `String`. +/// +/// ```rust +/// use widestring::U16String; +/// let s = "Test"; +/// // Create a wide string from the rust string +/// let wstr = U16String::from_str(s); +/// // Convert back to a rust string +/// let rust_str = wstr.to_string_lossy(); +/// assert_eq!(rust_str, "Test"); +/// ``` +pub type U16String = UString<u16>; + +/// An owned, mutable 32-bit wide string for FFI that is **not** nul-aware. +/// +/// `U32String` is not aware of nul values. Strings may or may not be nul-terminated, and may +/// contain invalid and ill-formed UTF-32 data. These strings are intended to be used with +/// FFI functions that directly use string length, where the strings are known to have proper +/// nul-termination already, or where strings are merely being passed through without modification. +/// +/// `U32CString` should be used instead if nul-aware 32-bit strings are required. +/// +/// `U32String` can be converted to and from many other standard Rust string types, including +/// `OsString` and `String`, making proper Unicode FFI safe and easy. +/// +/// # Examples +/// +/// The following example constructs a `U32String` and shows how to convert a `U32String` to a +/// regular Rust `String`. +/// +/// ```rust +/// use widestring::U32String; +/// let s = "Test"; +/// // Create a wide string from the rust string +/// let wstr = U32String::from_str(s); +/// // Convert back to a rust string +/// let rust_str = wstr.to_string_lossy(); +/// assert_eq!(rust_str, "Test"); +/// ``` +pub type U32String = UString<u32>; + +/// Alias for `U16String` or `U32String` depending on platform. Intended to match typical C `wchar_t` size on platform. +pub type WideString = UString<WideChar>; |