floem_editor_core/
char_buffer.rs

1extern crate alloc;
2
3use alloc::{borrow::Cow, rc::Rc, sync::Arc};
4use core::{borrow::Borrow, cmp::Ordering, fmt, hash, ops::Deref, str};
5
6/// This is a small memory buffer allocated on the stack to store a
7/// ‘string slice’ of exactly one character in length.
8///
9/// That is, this structure stores the result of converting [`char`] to [`prim@str`]
10/// (which can be accessed as [`&str`]).
11///
12/// In other words, this struct is a helper for performing `char -> &str`
13/// type conversion without heap allocation.
14///
15/// # Note
16///
17/// In general, it is not recommended to perform `char -> CharBuffer -> char`
18/// type conversions, as this may affect performance.
19///
20/// [`&str`]: https://doc.rust-lang.org/core/primitive.str.html
21///
22/// # Examples
23///
24/// ```
25/// use floem_editor_core::char_buffer::CharBuffer;
26///
27/// let word = "goodbye";
28///
29/// let mut chars_buf = word.chars().map(CharBuffer::new);
30///
31/// assert_eq!("g", chars_buf.next().unwrap().as_ref());
32/// assert_eq!("o", chars_buf.next().unwrap().as_ref());
33/// assert_eq!("o", chars_buf.next().unwrap().as_ref());
34/// assert_eq!("d", chars_buf.next().unwrap().as_ref());
35/// assert_eq!("b", chars_buf.next().unwrap().as_ref());
36/// assert_eq!("y", chars_buf.next().unwrap().as_ref());
37/// assert_eq!("e", chars_buf.next().unwrap().as_ref());
38///
39/// assert_eq!(None, chars_buf.next());
40///
41/// for (char, char_buf) in word.chars().zip(word.chars().map(CharBuffer::new)) {
42///     assert_eq!(char.to_string(), char_buf);
43/// }
44/// ```
45#[derive(Clone, Copy, PartialEq, Eq)]
46pub struct CharBuffer {
47    len: usize,
48    buf: [u8; 4],
49}
50
51/// The type of error returned when the conversion from [`prim@str`], [`String`] or their borrowed
52/// or native forms to [`CharBuffer`] fails.
53///
54/// This `structure` is created by various `CharBuffer::try_from` methods (for example,
55/// by the [`CharBuffer::try_from<&str>`] method).
56///
57/// See its documentation for more.
58///
59/// [`CharBuffer::try_from<&str>`]: CharBuffer::try_from<&str>
60#[derive(Copy, Clone, Debug, PartialEq, Eq)]
61pub struct CharBufferTryFromError(());
62
63impl CharBuffer {
64    /// Creates a new `CharBuffer` from the given [`char`].
65    ///
66    /// # Examples
67    ///
68    /// ```
69    /// use floem_editor_core::char_buffer::CharBuffer;
70    ///
71    /// let char_buf = CharBuffer::new('a');
72    /// assert_eq!("a", &char_buf);
73    ///
74    /// let string = "Some string";
75    /// let char_vec = string.chars().map(CharBuffer::new).collect::<Vec<_>>();
76    /// assert_eq!(
77    ///     ["S", "o", "m", "e", " ", "s", "t", "r", "i", "n", "g"].as_ref(),
78    ///     &char_vec
79    /// );
80    /// ```
81    #[inline]
82    pub fn new(char: char) -> Self {
83        let mut buf = [0; 4];
84        let len = char.encode_utf8(&mut buf).len();
85        Self { len, buf }
86    }
87
88    /// Converts a `CharBuffer` into an immutable string slice.
89    ///
90    /// # Examples
91    ///
92    /// ```
93    /// use floem_editor_core::char_buffer::CharBuffer;
94    ///
95    /// let char_buf = CharBuffer::from('r');
96    /// assert_eq!("r", char_buf.as_str());
97    /// ```
98    #[inline]
99    pub fn as_str(&self) -> &str {
100        self
101    }
102
103    /// Returns the length of a `&str` stored inside the `CharBuffer`, in bytes,
104    /// not [`char`]s or graphemes. In other words, it might not be what a human
105    /// considers the length of the string.
106    ///
107    /// # Examples
108    ///
109    /// ```
110    /// use floem_editor_core::char_buffer::CharBuffer;
111    ///
112    /// let f = CharBuffer::new('f');
113    /// assert_eq!(f.len(), 1);
114    ///
115    /// let fancy_f = CharBuffer::new('ƒ');
116    /// assert_eq!(fancy_f.len(), 2);
117    /// ```
118    #[inline]
119    pub fn len(&self) -> usize {
120        self.len
121    }
122
123    /// Always returns `false` since this structure can only be created from
124    /// [`char`], which cannot be empty.
125    ///
126    /// # Examples
127    ///
128    /// ```
129    /// use floem_editor_core::char_buffer::CharBuffer;
130    ///
131    /// let c = CharBuffer::new('\0');
132    /// assert!(!c.is_empty());
133    /// assert_eq!(c.len(), 1);
134    /// ```
135    #[inline]
136    pub fn is_empty(&self) -> bool {
137        false
138    }
139}
140
141impl From<char> for CharBuffer {
142    /// Creates a new [`CharBuffer`] from the given [`char`].
143    ///
144    /// Calling this function is the same as calling [`new`](CharBuffer::new)
145    /// function.
146    ///
147    /// # Example
148    ///
149    /// ```
150    /// use floem_editor_core::char_buffer::CharBuffer;
151    ///
152    /// let char_buf = CharBuffer::from('a');
153    /// assert_eq!("a", &char_buf);
154    ///
155    /// let string = "Some string";
156    /// let char_vec = string.chars().map(CharBuffer::from).collect::<Vec<_>>();
157    /// assert_eq!(
158    ///     ["S", "o", "m", "e", " ", "s", "t", "r", "i", "n", "g"].as_ref(),
159    ///     &char_vec
160    /// );
161    /// ```
162    #[inline]
163    fn from(char: char) -> Self {
164        Self::new(char)
165    }
166}
167
168impl From<&char> for CharBuffer {
169    /// Converts a `&char` into a [`CharBuffer`].
170    ///
171    /// # Example
172    ///
173    /// ```
174    /// use floem_editor_core::char_buffer::CharBuffer;
175    ///
176    /// let string = "Some string";
177    /// let char_vec = string.chars().collect::<Vec<_>>();
178    /// assert_eq!(
179    ///     ['S', 'o', 'm', 'e', ' ', 's', 't', 'r', 'i', 'n', 'g'].as_ref(),
180    ///     &char_vec
181    /// );
182    ///
183    /// let string_vec = char_vec.iter().map(CharBuffer::from).collect::<Vec<_>>();
184    ///
185    /// assert_eq!(
186    ///     ["S", "o", "m", "e", " ", "s", "t", "r", "i", "n", "g"].as_ref(),
187    ///     &string_vec
188    /// );
189    /// ````
190    #[inline]
191    fn from(char: &char) -> Self {
192        Self::new(*char)
193    }
194}
195
196impl From<&mut char> for CharBuffer {
197    /// Converts a `&mut char` into a [`CharBuffer`].
198    ///
199    /// # Example
200    ///
201    /// ```
202    /// use floem_editor_core::char_buffer::CharBuffer;
203    ///
204    /// let string = "Some string";
205    /// let mut char_vec = string.chars().collect::<Vec<_>>();
206    /// assert_eq!(
207    ///     ['S', 'o', 'm', 'e', ' ', 's', 't', 'r', 'i', 'n', 'g'].as_ref(),
208    ///     &char_vec
209    /// );
210    ///
211    /// let string_vec = char_vec
212    ///     .iter_mut()
213    ///     .map(CharBuffer::from)
214    ///     .collect::<Vec<_>>();
215    ///
216    /// assert_eq!(
217    ///     ["S", "o", "m", "e", " ", "s", "t", "r", "i", "n", "g"].as_ref(),
218    ///     &string_vec
219    /// );
220    /// ````
221    #[inline]
222    fn from(char: &mut char) -> Self {
223        Self::new(*char)
224    }
225}
226
227impl From<CharBuffer> for char {
228    /// Creates a new [`char`] from the given reference to [`CharBuffer`].
229    ///
230    /// # Note
231    ///
232    /// In general, it is not recommended to perform `char -> CharBuffer -> char`
233    /// type conversions, as this may affect performance.
234    ///
235    /// # Example
236    ///
237    /// ```
238    /// use floem_editor_core::char_buffer::CharBuffer;
239    ///
240    /// let char_buf = CharBuffer::from('a');
241    /// let char: char = char_buf.into();
242    /// assert_eq!('a', char);
243    ///
244    /// let string = "Some string";
245    ///
246    /// // Such type conversions are not recommended, use `char` directly
247    /// let char_vec = string
248    ///     .chars()
249    ///     .map(CharBuffer::from)
250    ///     .map(char::from)
251    ///     .collect::<Vec<_>>();
252    ///
253    /// assert_eq!(
254    ///     ['S', 'o', 'm', 'e', ' ', 's', 't', 'r', 'i', 'n', 'g'].as_ref(),
255    ///     &char_vec
256    /// );
257    /// ````
258    #[inline]
259    fn from(char: CharBuffer) -> Self {
260        // SAFETY: The structure stores a valid utf8 character
261        unsafe { char.chars().next().unwrap_unchecked() }
262    }
263}
264
265impl From<&CharBuffer> for char {
266    /// Converts a `&CharBuffer` into a [`char`].
267    ///
268    /// # Note
269    ///
270    /// In general, it is not recommended to perform `char -> CharBuffer -> char`
271    /// type conversions, as this may affect performance.
272    ///
273    /// # Example
274    ///
275    /// ```
276    /// use floem_editor_core::char_buffer::CharBuffer;
277    ///
278    /// let char_buf = CharBuffer::from('a');
279    /// let char: char = char::from(&char_buf);
280    /// assert_eq!('a', char);
281    ///
282    /// let string = "Some string";
283    ///
284    /// // Such type conversions are not recommended, use `char` directly
285    /// let char_buf_vec = string.chars().map(CharBuffer::from).collect::<Vec<_>>();
286    /// let char_vec = char_buf_vec.iter().map(char::from).collect::<Vec<_>>();
287    ///
288    /// assert_eq!(
289    ///     ['S', 'o', 'm', 'e', ' ', 's', 't', 'r', 'i', 'n', 'g'].as_ref(),
290    ///     &char_vec
291    /// );
292    /// ````
293    #[inline]
294    fn from(char: &CharBuffer) -> Self {
295        // SAFETY: The structure stores a valid utf8 character
296        unsafe { char.chars().next().unwrap_unchecked() }
297    }
298}
299
300impl From<&CharBuffer> for CharBuffer {
301    /// Converts a `&CharBuffer` into a [`CharBuffer`].
302    ///
303    /// # Example
304    ///
305    /// ```
306    /// use floem_editor_core::char_buffer::CharBuffer;
307    ///
308    /// let char_buf1 = CharBuffer::from('a');
309    /// let char_buf2: CharBuffer = CharBuffer::from(&char_buf1);
310    /// assert_eq!(char_buf1, char_buf2);
311    ///
312    /// let string = "Some string";
313    /// let char_vec1 = string.chars().map(CharBuffer::from).collect::<Vec<_>>();
314    /// let char_vec2 = char_vec1.iter().map(CharBuffer::from).collect::<Vec<_>>();
315    ///
316    /// assert_eq!(char_vec1, char_vec2);
317    /// ````
318    #[inline]
319    fn from(char: &CharBuffer) -> Self {
320        *char
321    }
322}
323
324impl From<CharBuffer> for String {
325    /// Allocates an owned [`String`] from a single character.
326    ///
327    /// # Example
328    ///
329    /// ```
330    /// use floem_editor_core::char_buffer::CharBuffer;
331    ///
332    /// let c: CharBuffer = CharBuffer::from('a');
333    /// let s: String = String::from(c);
334    /// assert_eq!("a", &s[..]);
335    /// ```
336    #[inline]
337    fn from(char: CharBuffer) -> Self {
338        char.as_ref().to_string()
339    }
340}
341
342impl From<&CharBuffer> for String {
343    /// Allocates an owned [`String`] from a single character.
344    ///
345    /// # Example
346    ///
347    /// ```
348    /// use floem_editor_core::char_buffer::CharBuffer;
349    ///
350    /// let c: CharBuffer = CharBuffer::from('a');
351    /// let s: String = String::from(&c);
352    /// assert_eq!("a", &s[..]);
353    /// ```
354    #[inline]
355    fn from(char: &CharBuffer) -> Self {
356        char.as_ref().to_string()
357    }
358}
359
360impl<'a> From<&'a CharBuffer> for &'a str {
361    /// Converts a `&CharBuffer` into a [`prim@str`].
362    ///
363    /// # Example
364    ///
365    /// ```
366    /// use floem_editor_core::char_buffer::CharBuffer;
367    ///
368    /// let c: CharBuffer = CharBuffer::from('a');
369    /// let s: &str = From::from(&c);
370    /// assert_eq!("a", &s[..]);
371    /// ```
372    #[inline]
373    fn from(char: &'a CharBuffer) -> Self {
374        char
375    }
376}
377
378impl<'a> From<&'a CharBuffer> for Cow<'a, str> {
379    /// Converts a `&'a CharBuffer` into a [`Cow<'a, str>`].
380    ///
381    /// # Example
382    ///
383    /// ```
384    /// use floem_editor_core::char_buffer::CharBuffer;
385    /// use std::borrow::Cow;
386    ///
387    /// let c: CharBuffer = CharBuffer::from('a');
388    /// let s: Cow<str> = From::from(&c);
389    /// assert_eq!("a", &s[..]);
390    /// ```
391    /// [`Cow<'a, str>`]: https://doc.rust-lang.org/std/borrow/enum.Cow.html
392    #[inline]
393    fn from(s: &'a CharBuffer) -> Self {
394        Cow::Borrowed(&**s)
395    }
396}
397
398impl From<CharBuffer> for Cow<'_, CharBuffer> {
399    /// Converts a `CharBuffer` into a [`Cow<'_, CharBuffer>`].
400    ///
401    /// # Example
402    ///
403    /// ```
404    /// use floem_editor_core::char_buffer::CharBuffer;
405    /// use std::borrow::Cow;
406    ///
407    /// let c: CharBuffer = CharBuffer::from('a');
408    /// let s: Cow<CharBuffer> = From::from(c);
409    /// assert_eq!("a", &s[..]);
410    /// ```
411    /// [`Cow<'_, CharBuffer>`]: https://doc.rust-lang.org/std/borrow/enum.Cow.html
412    #[inline]
413    fn from(s: CharBuffer) -> Self {
414        Cow::Owned(s)
415    }
416}
417
418macro_rules! impl_from_to_ptr {
419    (
420        $(#[$meta:meta])*
421        $ptr:ident
422    ) => {
423        $(#[$meta])*
424        impl From<CharBuffer> for $ptr<str> {
425            #[inline]
426            fn from(s: CharBuffer) -> Self {
427                Self::from(&*s)
428            }
429        }
430
431        $(#[$meta])*
432        impl From<&CharBuffer> for $ptr<str> {
433            #[inline]
434            fn from(s: &CharBuffer) -> Self {
435                Self::from(&**s)
436            }
437        }
438    }
439}
440
441impl_from_to_ptr! {
442    /// Converts a `CharBuffer` into a [`Arc<str>`].
443    ///
444    /// # Example
445    ///
446    /// ```
447    /// use floem_editor_core::char_buffer::CharBuffer;
448    /// use std::sync::Arc;
449    ///
450    /// let c: CharBuffer = CharBuffer::from('a');
451    /// let s1: Arc<str> = From::from(&c);
452    /// assert_eq!("a", &s1[..]);
453    ///
454    /// let s2: Arc<str> = From::from(c);
455    /// assert_eq!("a", &s2[..]);
456    /// ```
457    /// [`Arc<str>`]: https://doc.rust-lang.org/std/sync/struct.Arc.html
458    Arc
459}
460
461impl_from_to_ptr! {
462    /// Converts a `CharBuffer` into a [`Box<str>`].
463    ///
464    /// # Example
465    ///
466    /// ```
467    /// use floem_editor_core::char_buffer::CharBuffer;
468    ///
469    /// let c: CharBuffer = CharBuffer::from('a');
470    /// let s1: Box<str> = From::from(&c);
471    /// assert_eq!("a", &s1[..]);
472    ///
473    /// let s2: Box<str> = From::from(c);
474    /// assert_eq!("a", &s2[..]);
475    /// ```
476    /// [`Box<str>`]: https://doc.rust-lang.org/std/boxed/struct.Box.html
477    Box
478}
479
480impl_from_to_ptr! {
481    /// Converts a `CharBuffer` into a [`Rc<str>`].
482    ///
483    /// # Example
484    ///
485    /// ```
486    /// use floem_editor_core::char_buffer::CharBuffer;
487    /// use std::rc::Rc;
488    ///
489    /// let c: CharBuffer = CharBuffer::from('a');
490    /// let s1: Rc<str> = From::from(&c);
491    /// assert_eq!("a", &s1[..]);
492    ///
493    /// let s2: Rc<str> = From::from(c);
494    /// assert_eq!("a", &s2[..]);
495    /// ```
496    /// [`Rc<str>`]: https://doc.rust-lang.org/std/rc/struct.Rc.html
497    Rc
498}
499
500macro_rules! impl_try_from {
501    ($lhs:ty) => {
502        impl TryFrom<$lhs> for CharBuffer {
503            type Error = CharBufferTryFromError;
504
505            fn try_from(str: $lhs) -> Result<Self, Self::Error> {
506                let mut chars = str.chars();
507                match (chars.next(), chars.next()) {
508                    (Some(char), None) => Ok(Self::new(char)),
509                    _ => Err(CharBufferTryFromError(())),
510                }
511            }
512        }
513    };
514}
515
516impl_try_from!(&str);
517impl_try_from!(&mut str);
518
519impl_try_from!(String);
520impl_try_from!(&String);
521impl_try_from!(&mut String);
522
523impl_try_from!(Box<str>);
524impl_try_from!(&Box<str>);
525impl_try_from!(&mut Box<str>);
526
527impl_try_from!(Arc<str>);
528impl_try_from!(&Arc<str>);
529impl_try_from!(&mut Arc<str>);
530
531impl_try_from!(Rc<str>);
532impl_try_from!(&Rc<str>);
533impl_try_from!(&mut Rc<str>);
534
535impl Deref for CharBuffer {
536    type Target = str;
537
538    #[inline]
539    fn deref(&self) -> &Self::Target {
540        // SAFETY:
541        // - This is the same buffer that we passed to `encode_utf8` during creating this structure,
542        //   so valid utf8 is stored there;
543        // - The length was directly calculated from the `&str` returned by the `encode_utf8` function
544        unsafe { str::from_utf8_unchecked(self.buf.get_unchecked(..self.len)) }
545    }
546}
547
548impl AsRef<str> for CharBuffer {
549    #[inline]
550    fn as_ref(&self) -> &str {
551        self
552    }
553}
554
555impl Borrow<str> for CharBuffer {
556    #[inline]
557    fn borrow(&self) -> &str {
558        self
559    }
560}
561
562#[allow(clippy::derived_hash_with_manual_eq)]
563impl hash::Hash for CharBuffer {
564    #[inline]
565    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
566        (**self).hash(hasher)
567    }
568}
569
570impl fmt::Debug for CharBuffer {
571    #[inline]
572    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
573        fmt::Debug::fmt(&**self, f)
574    }
575}
576
577impl fmt::Display for CharBuffer {
578    #[inline]
579    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
580        fmt::Display::fmt(&**self, f)
581    }
582}
583
584impl PartialOrd for CharBuffer {
585    #[inline]
586    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
587        Some(self.cmp(other))
588    }
589}
590
591impl Ord for CharBuffer {
592    #[inline]
593    fn cmp(&self, other: &Self) -> Ordering {
594        (**self).cmp(&**other)
595    }
596}
597
598macro_rules! impl_eq {
599    ($lhs:ty, $rhs: ty) => {
600        #[allow(unused_lifetimes)]
601        impl<'a, 'b> PartialEq<$rhs> for $lhs {
602            #[inline]
603            fn eq(&self, other: &$rhs) -> bool {
604                PartialEq::eq(&self[..], &other[..])
605            }
606        }
607
608        #[allow(unused_lifetimes)]
609        impl<'a, 'b> PartialEq<$lhs> for $rhs {
610            #[inline]
611            fn eq(&self, other: &$lhs) -> bool {
612                PartialEq::eq(&self[..], &other[..])
613            }
614        }
615    };
616}
617
618impl_eq! { CharBuffer, str }
619impl_eq! { CharBuffer, &'a str }
620impl_eq! { CharBuffer, &'a mut str }
621
622impl_eq! { CharBuffer, String }
623impl_eq! { CharBuffer, &'a String }
624impl_eq! { CharBuffer, &'a mut String }
625
626impl_eq! { Cow<'a, str>, CharBuffer }
627impl_eq! { Cow<'_, CharBuffer>, CharBuffer }
628
629#[allow(clippy::single_match)]
630#[test]
631fn test_char_buffer() {
632    #[cfg(miri)]
633    let mut string = String::from(
634        "
635    This is some text. Это некоторый текст. Αυτό είναι κάποιο κείμενο. 這是一些文字。",
636    );
637    #[cfg(not(miri))]
638    let mut string = String::from(
639        "
640    https://www.w3.org/2001/06/utf-8-test/UTF-8-demo.html
641
642    Original by Markus Kuhn, adapted for HTML by Martin Dürst.
643
644    UTF-8 encoded sample plain-text file
645    ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
646
647    Markus Kuhn [ˈmaʳkʊs kuːn] <[email protected]> — 1999-08-20
648
649
650    The ASCII compatible UTF-8 encoding of ISO 10646 and Unicode
651    plain-text files is defined in RFC 2279 and in ISO 10646-1 Annex R.
652
653
654    Using Unicode/UTF-8, you can write in emails and source code things such as
655
656    Mathematics and Sciences:
657
658      ∮ E⋅da = Q,  n → ∞, ∑ f(i) = ∏ g(i), ∀x∈ℝ: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β),
659
660      ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⊥ < a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (A ⇔ B),
661
662      2H₂ + O₂ ⇌ 2H₂O, R = 4.7 kΩ, ⌀ 200 mm
663
664    Linguistics and dictionaries:
665
666      ði ıntəˈnæʃənəl fəˈnɛtık əsoʊsiˈeıʃn
667      Y [ˈʏpsilɔn], Yen [jɛn], Yoga [ˈjoːgɑ]
668
669    APL:
670
671      ((V⍳V)=⍳⍴V)/V←,V    ⌷←⍳→⍴∆∇⊃‾⍎⍕⌈
672
673    Nicer typography in plain text files:
674
675      ╔══════════════════════════════════════════╗
676      ║                                          ║
677      ║   • ‘single’ and “double” quotes         ║
678      ║                                          ║
679      ║   • Curly apostrophes: “We’ve been here” ║
680      ║                                          ║
681      ║   • Latin-1 apostrophe and accents: '´`  ║
682      ║                                          ║
683      ║   • ‚deutsche‘ „Anführungszeichen“       ║
684      ║                                          ║
685      ║   • †, ‡, ‰, •, 3–4, —, −5/+5, ™, …      ║
686      ║                                          ║
687      ║   • ASCII safety test: 1lI|, 0OD, 8B     ║
688      ║                      ╭─────────╮         ║
689      ║   • the euro symbol: │ 14.95 € │         ║
690      ║                      ╰─────────╯         ║
691      ╚══════════════════════════════════════════╝
692
693    Greek (in Polytonic):
694
695      The Greek anthem:
696
697      Σὲ γνωρίζω ἀπὸ τὴν κόψη
698      τοῦ σπαθιοῦ τὴν τρομερή,
699      σὲ γνωρίζω ἀπὸ τὴν ὄψη
700      ποὺ μὲ βία μετράει τὴ γῆ.
701
702      ᾿Απ᾿ τὰ κόκκαλα βγαλμένη
703      τῶν ῾Ελλήνων τὰ ἱερά
704      καὶ σὰν πρῶτα ἀνδρειωμένη
705      χαῖρε, ὦ χαῖρε, ᾿Ελευθεριά!
706
707      From a speech of Demosthenes in the 4th century BC:
708
709      Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι,
710      ὅταν τ᾿ εἰς τὰ πράγματα ἀποβλέψω καὶ ὅταν πρὸς τοὺς
711      λόγους οὓς ἀκούω· τοὺς μὲν γὰρ λόγους περὶ τοῦ
712      τιμωρήσασθαι Φίλιππον ὁρῶ γιγνομένους, τὰ δὲ πράγματ᾿
713      εἰς τοῦτο προήκοντα,  ὥσθ᾿ ὅπως μὴ πεισόμεθ᾿ αὐτοὶ
714      πρότερον κακῶς σκέψασθαι δέον. οὐδέν οὖν ἄλλο μοι δοκοῦσιν
715      οἱ τὰ τοιαῦτα λέγοντες ἢ τὴν ὑπόθεσιν, περὶ ἧς βουλεύεσθαι,
716      οὐχὶ τὴν οὖσαν παριστάντες ὑμῖν ἁμαρτάνειν. ἐγὼ δέ, ὅτι μέν
717      ποτ᾿ ἐξῆν τῇ πόλει καὶ τὰ αὑτῆς ἔχειν ἀσφαλῶς καὶ Φίλιππον
718      τιμωρήσασθαι, καὶ μάλ᾿ ἀκριβῶς οἶδα· ἐπ᾿ ἐμοῦ γάρ, οὐ πάλαι
719      γέγονεν ταῦτ᾿ ἀμφότερα· νῦν μέντοι πέπεισμαι τοῦθ᾿ ἱκανὸν
720      προλαβεῖν ἡμῖν εἶναι τὴν πρώτην, ὅπως τοὺς συμμάχους
721      σώσομεν. ἐὰν γὰρ τοῦτο βεβαίως ὑπάρξῃ, τότε καὶ περὶ τοῦ
722      τίνα τιμωρήσεταί τις καὶ ὃν τρόπον ἐξέσται σκοπεῖν· πρὶν δὲ
723      τὴν ἀρχὴν ὀρθῶς ὑποθέσθαι, μάταιον ἡγοῦμαι περὶ τῆς
724      τελευτῆς ὁντινοῦν ποιεῖσθαι λόγον.
725
726      Δημοσθένους, Γ´ ᾿Ολυνθιακὸς
727
728    Georgian:
729
730      From a Unicode conference invitation:
731
732      გთხოვთ ახლავე გაიაროთ რეგისტრაცია Unicode-ის მეათე საერთაშორისო
733      კონფერენციაზე დასასწრებად, რომელიც გაიმართება 10-12 მარტს,
734      ქ. მაინცში, გერმანიაში. კონფერენცია შეჰკრებს ერთად მსოფლიოს
735      ექსპერტებს ისეთ დარგებში როგორიცაა ინტერნეტი და Unicode-ი,
736      ინტერნაციონალიზაცია და ლოკალიზაცია, Unicode-ის გამოყენება
737      ოპერაციულ სისტემებსა, და გამოყენებით პროგრამებში, შრიფტებში,
738      ტექსტების დამუშავებასა და მრავალენოვან კომპიუტერულ სისტემებში.
739
740    Russian:
741
742      From a Unicode conference invitation:
743
744      Зарегистрируйтесь сейчас на Десятую Международную Конференцию по
745      Unicode, которая состоится 10-12 марта 1997 года в Майнце в Германии.
746      Конференция соберет широкий круг экспертов по  вопросам глобального
747      Интернета и Unicode, локализации и интернационализации, воплощению и
748      применению Unicode в различных операционных системах и программных
749      приложениях, шрифтах, верстке и многоязычных компьютерных системах.
750
751    Thai (UCS Level 2):
752
753      Excerpt from a poetry on The Romance of The Three Kingdoms (a Chinese
754      classic 'San Gua'):
755
756      [----------------------------|------------------------]
757        ๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช  พระปกเกศกองบู๊กู้ขึ้นใหม่
758      สิบสองกษัตริย์ก่อนหน้าแลถัดไป       สององค์ไซร้โง่เขลาเบาปัญญา
759        ทรงนับถือขันทีเป็นที่พึ่ง           บ้านเมืองจึงวิปริตเป็นนักหนา
760      โฮจิ๋นเรียกทัพทั่วหัวเมืองมา         หมายจะฆ่ามดชั่วตัวสำคัญ
761        เหมือนขับไสไล่เสือจากเคหา      รับหมาป่าเข้ามาเลยอาสัญ
762      ฝ่ายอ้องอุ้นยุแยกให้แตกกัน          ใช้สาวนั้นเป็นชนวนชื่นชวนใจ
763        พลันลิฉุยกุยกีกลับก่อเหตุ          ช่างอาเพศจริงหนาฟ้าร้องไห้
764      ต้องรบราฆ่าฟันจนบรรลัย           ฤๅหาใครค้ำชูกู้บรรลังก์ ฯ
765
766      (The above is a two-column text. If combining characters are handled
767      correctly, the lines of the second column should be aligned with the
768      | character above.)
769
770    Ethiopian:
771
772      Proverbs in the Amharic language:
773
774      ሰማይ አይታረስ ንጉሥ አይከሰስ።
775      ብላ ካለኝ እንደአባቴ በቆመጠኝ።
776      ጌጥ ያለቤቱ ቁምጥና ነው።
777      ደሀ በሕልሙ ቅቤ ባይጠጣ ንጣት በገደለው።
778      የአፍ ወለምታ በቅቤ አይታሽም።
779      አይጥ በበላ ዳዋ ተመታ።
780      ሲተረጉሙ ይደረግሙ።
781      ቀስ በቀስ፥ ዕንቁላል በእግሩ ይሄዳል።
782      ድር ቢያብር አንበሳ ያስር።
783      ሰው እንደቤቱ እንጅ እንደ ጉረቤቱ አይተዳደርም።
784      እግዜር የከፈተውን ጉሮሮ ሳይዘጋው አይድርም።
785      የጎረቤት ሌባ፥ ቢያዩት ይስቅ ባያዩት ያጠልቅ።
786      ሥራ ከመፍታት ልጄን ላፋታት።
787      ዓባይ ማደሪያ የለው፥ ግንድ ይዞ ይዞራል።
788      የእስላም አገሩ መካ የአሞራ አገሩ ዋርካ።
789      ተንጋሎ ቢተፉ ተመልሶ ባፉ።
790      ወዳጅህ ማር ቢሆን ጨርስህ አትላሰው።
791      እግርህን በፍራሽህ ልክ ዘርጋ።
792
793    Runes:
794
795      ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ
796
797      (Old English, which transcribed into Latin reads 'He cwaeth that he
798      bude thaem lande northweardum with tha Westsae.' and means 'He said
799      that he lived in the northern land near the Western Sea.')
800
801    Braille:
802
803      ⡌⠁⠧⠑ ⠼⠁⠒  ⡍⠜⠇⠑⠹⠰⠎ ⡣⠕⠌
804
805      ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠙⠑⠁⠙⠒ ⠞⠕ ⠃⠑⠛⠔ ⠺⠊⠹⠲ ⡹⠻⠑ ⠊⠎ ⠝⠕ ⠙⠳⠃⠞
806      ⠱⠁⠞⠑⠧⠻ ⠁⠃⠳⠞ ⠹⠁⠞⠲ ⡹⠑ ⠗⠑⠛⠊⠌⠻ ⠕⠋ ⠙⠊⠎ ⠃⠥⠗⠊⠁⠇ ⠺⠁⠎
807      ⠎⠊⠛⠝⠫ ⠃⠹ ⠹⠑ ⠊⠇⠻⠛⠹⠍⠁⠝⠂ ⠹⠑ ⠊⠇⠻⠅⠂ ⠹⠑ ⠥⠝⠙⠻⠞⠁⠅⠻⠂
808      ⠁⠝⠙ ⠹⠑ ⠡⠊⠑⠋ ⠍⠳⠗⠝⠻⠲ ⡎⠊⠗⠕⠕⠛⠑ ⠎⠊⠛⠝⠫ ⠊⠞⠲ ⡁⠝⠙
809      ⡎⠊⠗⠕⠕⠛⠑⠰⠎ ⠝⠁⠍⠑ ⠺⠁⠎ ⠛⠕⠕⠙ ⠥⠏⠕⠝ ⠰⡡⠁⠝⠛⠑⠂ ⠋⠕⠗ ⠁⠝⠹⠹⠔⠛ ⠙⠑
810      ⠡⠕⠎⠑ ⠞⠕ ⠏⠥⠞ ⠙⠊⠎ ⠙⠁⠝⠙ ⠞⠕⠲
811
812      ⡕⠇⠙ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲
813
814      ⡍⠔⠙⠖ ⡊ ⠙⠕⠝⠰⠞ ⠍⠑⠁⠝ ⠞⠕ ⠎⠁⠹ ⠹⠁⠞ ⡊ ⠅⠝⠪⠂ ⠕⠋ ⠍⠹
815      ⠪⠝ ⠅⠝⠪⠇⠫⠛⠑⠂ ⠱⠁⠞ ⠹⠻⠑ ⠊⠎ ⠏⠜⠞⠊⠊⠥⠇⠜⠇⠹ ⠙⠑⠁⠙ ⠁⠃⠳⠞
816      ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ ⡊ ⠍⠊⠣⠞ ⠙⠁⠧⠑ ⠃⠑⠲ ⠔⠊⠇⠔⠫⠂ ⠍⠹⠎⠑⠇⠋⠂ ⠞⠕
817      ⠗⠑⠛⠜⠙ ⠁ ⠊⠕⠋⠋⠔⠤⠝⠁⠊⠇ ⠁⠎ ⠹⠑ ⠙⠑⠁⠙⠑⠌ ⠏⠊⠑⠊⠑ ⠕⠋ ⠊⠗⠕⠝⠍⠕⠝⠛⠻⠹
818      ⠔ ⠹⠑ ⠞⠗⠁⠙⠑⠲ ⡃⠥⠞ ⠹⠑ ⠺⠊⠎⠙⠕⠍ ⠕⠋ ⠳⠗ ⠁⠝⠊⠑⠌⠕⠗⠎
819      ⠊⠎ ⠔ ⠹⠑ ⠎⠊⠍⠊⠇⠑⠆ ⠁⠝⠙ ⠍⠹ ⠥⠝⠙⠁⠇⠇⠪⠫ ⠙⠁⠝⠙⠎
820      ⠩⠁⠇⠇ ⠝⠕⠞ ⠙⠊⠌⠥⠗⠃ ⠊⠞⠂ ⠕⠗ ⠹⠑ ⡊⠳⠝⠞⠗⠹⠰⠎ ⠙⠕⠝⠑ ⠋⠕⠗⠲ ⡹⠳
821      ⠺⠊⠇⠇ ⠹⠻⠑⠋⠕⠗⠑ ⠏⠻⠍⠊⠞ ⠍⠑ ⠞⠕ ⠗⠑⠏⠑⠁⠞⠂ ⠑⠍⠏⠙⠁⠞⠊⠊⠁⠇⠇⠹⠂ ⠹⠁⠞
822      ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲
823
824      (The first couple of paragraphs of \"A Christmas Carol\" by Dickens)
825
826    Compact font selection example text:
827
828      ABCDEFGHIJKLMNOPQRSTUVWXYZ /0123456789
829      abcdefghijklmnopqrstuvwxyz £©µÀÆÖÞßéöÿ
830      –—‘“”„†•…‰™œŠŸž€ ΑΒΓΔΩαβγδω АБВГДабвгд
831      ∀∂∈ℝ∧∪≡∞ ↑↗↨↻⇣ ┐┼╔╘░►☺♀ fi�⑀₂ἠḂӥẄɐː⍎אԱა
832
833    Greetings in various languages:
834
835      Hello world, Καλημέρα κόσμε, コンニチハ
836
837    Box drawing alignment tests:                                          █
838839      ╔══╦══╗  ┌──┬──┐  ╭──┬──╮  ╭──┬──╮  ┏━━┳━━┓  ┎┒┏┑   ╷  ╻ ┏┯┓ ┌┰┐    ▊ ╱╲╱╲╳╳╳
840      ║┌─╨─┐║  │╔═╧═╗│  │╒═╪═╕│  │╓─╁─╖│  ┃┌─╂─┐┃  ┗╃╄┙  ╶┼╴╺╋╸┠┼┨ ┝╋┥    ▋ ╲╱╲╱╳╳╳
841      ║│╲ ╱│║  │║   ║│  ││ │ ││  │║ ┃ ║│  ┃│ ╿ │┃  ┍╅╆┓   ╵  ╹ ┗┷┛ └┸┘    ▌ ╱╲╱╲╳╳╳
842      ╠╡ ╳ ╞╣  ├╢   ╟┤  ├┼─┼─┼┤  ├╫─╂─╫┤  ┣┿╾┼╼┿┫  ┕┛┖┚     ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳
843      ║│╱ ╲│║  │║   ║│  ││ │ ││  │║ ┃ ║│  ┃│ ╽ │┃  ░░▒▒▓▓██ ┊  ┆ ╎ ╏  ┇ ┋ ▎
844      ║└─╥─┘║  │╚═╤═╝│  │╘═╪═╛│  │╙─╀─╜│  ┃└─╂─┘┃  ░░▒▒▓▓██ ┊  ┆ ╎ ╏  ┇ ┋ ▏
845      ╚══╩══╝  └──┴──┘  ╰──┴──╯  ╰──┴──╯  ┗━━┻━━┛           └╌╌┘ ╎ ┗╍╍┛ ┋  ▁▂▃▄▅▆▇█
846
847",
848    );
849
850    match CharBuffer::try_from(string.as_str()) {
851        Ok(_) => panic!("This should fail because of long string"),
852        Err(_) => {}
853    }
854
855    match CharBuffer::try_from(string.as_mut_str()) {
856        Ok(_) => panic!("This should fail because of long string"),
857        Err(_) => {}
858    }
859
860    match CharBuffer::try_from(&string) {
861        Ok(_) => panic!("This should fail because of long string"),
862        Err(_) => {}
863    }
864
865    match CharBuffer::try_from(&mut string) {
866        Ok(_) => panic!("This should fail because of long string"),
867        Err(_) => {}
868    }
869
870    match CharBuffer::try_from(string.clone()) {
871        Ok(_) => panic!("This should fail because of long string"),
872        Err(_) => {}
873    }
874
875    let mut some_box: Box<str> = Box::from(string.clone());
876
877    match CharBuffer::try_from(&some_box) {
878        Ok(_) => panic!("This should fail because of long string"),
879        Err(_) => {}
880    }
881
882    match CharBuffer::try_from(&mut some_box) {
883        Ok(_) => panic!("This should fail because of long string"),
884        Err(_) => {}
885    }
886
887    match CharBuffer::try_from(some_box) {
888        Ok(_) => panic!("This should fail because of long string"),
889        Err(_) => {}
890    }
891
892    let mut some_arc: Arc<str> = Arc::from(string.clone());
893
894    match CharBuffer::try_from(&some_arc) {
895        Ok(_) => panic!("This should fail because of long string"),
896        Err(_) => {}
897    }
898
899    match CharBuffer::try_from(&mut some_arc) {
900        Ok(_) => panic!("This should fail because of long string"),
901        Err(_) => {}
902    }
903
904    match CharBuffer::try_from(some_arc) {
905        Ok(_) => panic!("This should fail because of long string"),
906        Err(_) => {}
907    }
908
909    let mut some_rc: Rc<str> = Rc::from(string.clone());
910
911    match CharBuffer::try_from(&some_rc) {
912        Ok(_) => panic!("This should fail because of long string"),
913        Err(_) => {}
914    }
915
916    match CharBuffer::try_from(&mut some_rc) {
917        Ok(_) => panic!("This should fail because of long string"),
918        Err(_) => {}
919    }
920
921    match CharBuffer::try_from(some_rc) {
922        Ok(_) => panic!("This should fail because of long string"),
923        Err(_) => {}
924    }
925
926    let hash_builder = std::collections::hash_map::RandomState::default();
927
928    fn make_hash<Q, S>(hash_builder: &S, val: &Q) -> u64
929    where
930        Q: std::hash::Hash + ?Sized,
931        S: core::hash::BuildHasher,
932    {
933        hash_builder.hash_one(val)
934    }
935
936    for mut char in string.chars() {
937        let mut char_string = char.to_string();
938
939        assert_eq!(CharBuffer::new(char), char_string);
940        assert_eq!(CharBuffer::new(char).as_str(), char_string);
941        assert_eq!(CharBuffer::new(char).len(), char_string.len());
942        assert_eq!(CharBuffer::from(char), char_string);
943        assert_eq!(CharBuffer::from(&char), char_string);
944        assert_eq!(CharBuffer::from(&mut char), char_string);
945
946        let char_buf = CharBuffer::new(char);
947
948        assert_eq!(
949            make_hash(&hash_builder, &char_buf),
950            make_hash(&hash_builder, &char_string)
951        );
952
953        assert_eq!(CharBuffer::new(char), char_buf);
954        assert_eq!(CharBuffer::new(char), CharBuffer::from(&char_buf));
955        assert_eq!(&*char_buf, char_string.as_str());
956        assert_eq!(char_buf.as_ref(), char_string.as_str());
957        let str: &str = char_buf.borrow();
958        assert_eq!(str, char_string.as_str());
959
960        assert_eq!(char::from(&char_buf), char);
961        assert_eq!(char::from(char_buf), char);
962        assert_eq!(String::from(char_buf), char_string);
963        assert_eq!(String::from(&char_buf), char_string);
964
965        let str: &str = From::from(&char_buf);
966        assert_eq!(str, char_string);
967
968        let str: Cow<str> = From::from(&char_buf);
969        assert_eq!(str, char_string);
970
971        let str: Cow<CharBuffer> = From::from(char_buf);
972        assert_eq!(str.as_str(), char_string);
973
974        let str: Arc<str> = From::from(char_buf);
975        assert_eq!(&str[..], char_string);
976
977        let str: Arc<str> = From::from(&char_buf);
978        assert_eq!(&str[..], char_string);
979
980        let str: Box<str> = From::from(char_buf);
981        assert_eq!(&str[..], char_string);
982
983        let str: Box<str> = From::from(&char_buf);
984        assert_eq!(&str[..], char_string);
985
986        let str: Rc<str> = From::from(char_buf);
987        assert_eq!(&str[..], char_string);
988
989        let str: Rc<str> = From::from(&char_buf);
990        assert_eq!(&str[..], char_string);
991
992        match CharBuffer::try_from(char_string.as_str()) {
993            Ok(char_buf) => {
994                assert_eq!(char_buf, char_string.as_str());
995                assert_eq!(char_string.as_str(), char_buf);
996            }
997            Err(_) => panic!("This should not fail because of single char"),
998        }
999        match CharBuffer::try_from(char_string.as_mut_str()) {
1000            Ok(char_buf) => {
1001                assert_eq!(char_buf, char_string.as_mut_str());
1002                assert_eq!(char_string.as_mut_str(), char_buf);
1003            }
1004            Err(_) => panic!("This should not fail because of single char"),
1005        }
1006
1007        match CharBuffer::try_from(&char_string) {
1008            Ok(char_buf) => {
1009                assert_eq!(char_buf, &char_string);
1010                assert_eq!(&char_string, char_buf);
1011            }
1012            Err(_) => panic!("This should not fail because of single char"),
1013        }
1014        match CharBuffer::try_from(&mut char_string) {
1015            Ok(char_buf) => {
1016                assert_eq!(char_buf, &mut char_string);
1017                assert_eq!(&mut char_string, char_buf);
1018            }
1019            Err(_) => panic!("This should not fail because of single char"),
1020        }
1021        match CharBuffer::try_from(char_string.clone()) {
1022            Ok(char_buf) => {
1023                assert_eq!(char_buf, char_string);
1024                assert_eq!(char_string, char_buf);
1025            }
1026            Err(_) => panic!("This should not fail because of single char"),
1027        }
1028
1029        let mut some_box: Box<str> = Box::from(char_string.clone());
1030
1031        match CharBuffer::try_from(&some_box) {
1032            Ok(char_buf) => assert_eq!(char_buf, some_box.as_ref()),
1033            Err(_) => panic!("This should not fail because of single char"),
1034        }
1035        match CharBuffer::try_from(&mut some_box) {
1036            Ok(char_buf) => assert_eq!(char_buf, some_box.as_ref()),
1037            Err(_) => panic!("This should not fail because of single char"),
1038        }
1039        match CharBuffer::try_from(some_box) {
1040            Ok(char_buf) => assert_eq!(char_buf, char_string),
1041            Err(_) => panic!("This should not fail because of single char"),
1042        }
1043
1044        let mut some_arc: Arc<str> = Arc::from(char_string.clone());
1045
1046        match CharBuffer::try_from(&some_arc) {
1047            Ok(char_buf) => assert_eq!(char_buf, some_arc.as_ref()),
1048            Err(_) => panic!("This should not fail because of single char"),
1049        }
1050        match CharBuffer::try_from(&mut some_arc) {
1051            Ok(char_buf) => assert_eq!(char_buf, some_arc.as_ref()),
1052            Err(_) => panic!("This should not fail because of single char"),
1053        }
1054        match CharBuffer::try_from(some_arc) {
1055            Ok(char_buf) => assert_eq!(char_buf, char_string),
1056            Err(_) => panic!("This should not fail because of single char"),
1057        }
1058
1059        let mut some_rc: Rc<str> = Rc::from(char_string.clone());
1060
1061        match CharBuffer::try_from(&some_rc) {
1062            Ok(char_buf) => assert_eq!(char_buf, some_rc.as_ref()),
1063            Err(_) => panic!("This should not fail because of single char"),
1064        }
1065        match CharBuffer::try_from(&mut some_rc) {
1066            Ok(char_buf) => assert_eq!(char_buf, some_rc.as_ref()),
1067            Err(_) => panic!("This should not fail because of single char"),
1068        }
1069        match CharBuffer::try_from(some_rc) {
1070            Ok(char_buf) => assert_eq!(char_buf, char_string),
1071            Err(_) => panic!("This should not fail because of single char"),
1072        }
1073    }
1074}