1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
//! This library introduces two macros [`wch`] and [`wchz`] to create UTF-16 or
//! UTF-32 wide strings at compiler time, like `L` string literals in C.
//!
//! # Example
//!
//! ```
//! use wchar::{wch, wchz, wchar_t};
//!
//! // Equivalent to `#define RUST L"Rust"` in C.
//! const RUST: &[wchar_t] = wch!("Rust\0"); // C strings are nul-terminated.
//! // Equivalent to `#define ALSO_RUST L"Rust"` in C.
//! const ALSO_RUST: &[wchar_t] = wchz!("Rust");
//!
//! assert_eq!(RUST, &['R' as wchar_t, 'u' as wchar_t, 's' as wchar_t, 't' as wchar_t, 0x0000]);
//! assert_eq!(RUST, ALSO_RUST);
//! ```

#![no_std]

cfg_if::cfg_if! {
    if #[cfg(wchar_t = "u16")] {
        /// Platform wide character type.
        #[allow(non_camel_case_types)]
        pub type wchar_t = u16;

        #[doc(hidden)]
        #[macro_export]
        macro_rules! __expand_platform_wchar {
            ($macro:ident, $string:literal) => {
                $crate::_impl::$macro!(u16, $string)
            };
        }
    } else if #[cfg(wchar_t = "u32")] {
        /// Platform wide character type.
        #[allow(non_camel_case_types)]
        pub type wchar_t = u32;

        #[doc(hidden)]
        #[macro_export]
        macro_rules! __expand_platform_wchar {
            ($macro:ident, $string:literal) => {
                $crate::_impl::$macro!(u32, $string)
            };
        }
    } else if #[cfg(wchar_t = "i32")] {
        /// Platform wide character type.
        #[allow(non_camel_case_types)]
        pub type wchar_t = i32;

        #[doc(hidden)]
        #[macro_export]
        macro_rules! __expand_platform_wchar {
            ($macro:ident, $string:literal) => {
                $crate::_impl::$macro!(i32, $string)
            };
        }
    } else {
        #[doc(hidden)]
        #[macro_export]
        macro_rules! __expand_platform_wchar {
            ($macro:ident, $string:literal) => {
                $crate::_core::compile_error!("native wchar_t not support for this platform");
            };
        }
    }
}

#[doc(hidden)]
pub use core as _core;
#[doc(hidden)]
pub use wchar_impl as _impl;

/// Generate a UTF-16 or UTF-32 wide string from the given string literal.
///
/// The generated output takes the form of a slice of wide characters.
///
/// The first argument is the output character type, if no type is specfied the
/// platform native `wchar_t` will be used.
///
/// # Notes
///
/// Whilst this macro can be used for C-style nul-terminated wide strings, no
/// validations are made about internal nul characters. If your strings need to
/// be nul-terminated it is recommended to use [`wchz`].
///
/// # Examples
///
/// Basic example (platform native):
///
/// ```
/// # use wchar::{wch, wchar_t};
/// const WIDE: &[wchar_t] = wch!("foo");
/// ```
///
/// UTF-16 example:
///
/// ```
/// # use wchar::wch;
/// let wide_str = wch!(u16, "foo");
/// let expected = &[0x0066, 0x006F, 0x006F];
///
/// assert_eq!(wide_str, expected);
/// ```
///
/// UTF-32 example:
///
/// ```
/// # use wchar::wch;
/// let wide_str = wch!(u32, "foo");
/// let expected = &[0x0000_0066, 0x0000_006F, 0x0000_006F];
///
/// assert_eq!(wide_str, expected);
/// ```
#[macro_export]
macro_rules! wch {
    ($ty:ident, $string:literal) => {
        $crate::_impl::wch!($ty, $string)
    };
    ($string:literal) => {
        $crate::__expand_platform_wchar!(wch, $string)
    };
}

/// Generate a C-style nul-terminated UTF-16 or UTF-32 wide string from the
/// given string literal.
///
/// Validations are made that the given string does not contain nul characters.
///
/// The generated output takes the form of a slice of wide characters, with a
/// nul-terminator as the last wide character.
///
/// The first argument is the output character type, if no type is specfied the
/// platform native `wchar_t` will be used.
///
/// # Examples
///
/// Basic example (platform native):
///
/// ```
/// # use wchar::{wchz, wchar_t};
/// const WIDE: &[wchar_t] = wchz!("foo");
/// ```
///
/// UTF-16 example:
///
/// ```
/// # use wchar::wchz;
/// let wide_str = wchz!(u16, "bar");
/// let expected = &[0x0062, 0x0061, 0x0072, 0x0000];
///
/// assert_eq!(wide_str, expected);
/// ```
///
/// UTF-32 example:
///
/// ```
/// # use wchar::wchz;
/// let wide_str = wchz!(u32, "bar");
/// let expected = &[0x0000_0062, 0x0000_0061, 0x0000_0072, 0x0000_0000];
///
/// assert_eq!(wide_str, expected);
/// ```
#[macro_export]
macro_rules! wchz {
    ($ty:ident, $string:literal) => {
        $crate::_impl::wchz!($ty, $string)
    };
    ($string:literal) => {
        $crate::__expand_platform_wchar!(wchz, $string)
    };
}