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
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Determine displayed width of `char` and `str` types according to //! [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/) //! rules. //! //! ```rust //! extern crate unicode_width; //! //! use unicode_width::UnicodeWidthStr; //! //! fn main() { //! let teststr = "Hello, world!"; //! let width = UnicodeWidthStr::width(teststr); //! println!("{}", teststr); //! println!("The above string is {} columns wide.", width); //! let width = teststr.width_cjk(); //! println!("The above string is {} columns wide (CJK).", width); //! } //! ``` //! //! # features //! //! unicode-width supports a `no_std` feature. This eliminates dependence //! on std, and instead uses equivalent functions from core. //! //! # crates.io //! //! You can use this package in your project by adding the following //! to your `Cargo.toml`: //! //! ```toml //! [dependencies] //! unicode-width = "0.1.1" //! ``` #![deny(missing_docs, unsafe_code)] #![doc(html_logo_url = "https://unicode-rs.github.io/unicode-rs_sm.png", html_favicon_url = "https://unicode-rs.github.io/unicode-rs_sm.png")] #![cfg_attr(feature = "no_std", no_std)] #![cfg_attr(feature = "no_std", feature(no_std, core, core_prelude, core_slice_ext, core_str_ext))] #![cfg_attr(test, feature(test, unicode))] #[cfg(feature = "no_std")] #[macro_use] extern crate core; #[cfg(all(test, feature = "no_std"))] #[macro_use] extern crate std; #[cfg(test)] extern crate test; #[cfg(feature = "no_std")] use core::prelude::*; use tables::charwidth as cw; pub use tables::UNICODE_VERSION; #[cfg(feature = "no_std")] use core::ops::Add; #[cfg(not(feature = "no_std"))] use std::ops::Add; mod tables; #[cfg(test)] mod tests; /// Methods for determining displayed width of Unicode characters. pub trait UnicodeWidthChar { /// Returns the character's displayed width in columns, or `None` if the /// character is a control character other than `'\x00'`. /// /// This function treats characters in the Ambiguous category according /// to [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/) /// as 1 column wide. This is consistent with the recommendations for non-CJK /// contexts, or when the context cannot be reliably determined. fn width(self) -> Option<usize>; /// Returns the character's displayed width in columns, or `None` if the /// character is a control character other than `'\x00'`. /// /// This function treats characters in the Ambiguous category according /// to [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/) /// as 2 columns wide. This is consistent with the recommendations for /// CJK contexts. fn width_cjk(self) -> Option<usize>; } impl UnicodeWidthChar for char { #[inline] fn width(self) -> Option<usize> { cw::width(self, false) } #[inline] fn width_cjk(self) -> Option<usize> { cw::width(self, true) } } /// Methods for determining displayed width of Unicode strings. pub trait UnicodeWidthStr { /// Returns the string's displayed width in columns. /// /// Control characters are treated as having zero width. /// /// This function treats characters in the Ambiguous category according /// to [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/) /// as 1 column wide. This is consistent with the recommendations for /// non-CJK contexts, or when the context cannot be reliably determined. fn width<'a>(&'a self) -> usize; /// Returns the string's displayed width in columns. /// /// Control characters are treated as having zero width. /// /// This function treats characters in the Ambiguous category according /// to [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/) /// as 2 column wide. This is consistent with the recommendations for /// CJK contexts. fn width_cjk<'a>(&'a self) -> usize; } impl UnicodeWidthStr for str { #[inline] fn width(&self) -> usize { self.chars().map(|c| cw::width(c, false).unwrap_or(0)).fold(0, Add::add) } #[inline] fn width_cjk(&self) -> usize { self.chars().map(|c| cw::width(c, true).unwrap_or(0)).fold(0, Add::add) } }