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
//! Basic Text strings and I/O streams
//!
//! This crate provides several utilities for working with [Basic Text].
//!
//!  - [`TextString`] and [`TextStr`] are similar to the standard library's
//!    [`String`] and [`str`], but use the Basic Text string format, along with
//!    a [`text!("...")` macro] for Basic Text string literals.
//!
//!  - [`TextReader`] and [`TextWriter`] are input and output streams which use
//!    the Basic Text stream format. On input, content is converted in a way
//!    which is lossy with respect to the original bytestream. Output uses the
//!    "strict" conversion method, in which invalid content is diagnosed with
//!    errors.
//!
//!  - [`BufReadText`], an extension trait that adds [`text_lines`] and
//!    [`text_lines_lossy`] to [`BufRead`] implementations for reading lines
//!    from an input stream as `BasicText` strings.
//!
//!  - [`TextDuplexer`] is a [`Duplex`] for reading and writing on an
//!    interactive stream using Basic Text.
//!
//! # Examples
//!
//! Working with `TextString` and company is overall similar to working with
//! `String` and company, but with a little more syntax in some places:
//!
//! ```rust
//! use basic_text::{text, text_substr, ReadText, TextReader, TextString, TextWriter, WriteText};
//! use std::io::{stdin, stdout, Write};
//!
//! // Wrap stdout in an output stream that ensures that the output is
//! // Basic Text.
//! let mut stream = TextWriter::new(stdout());
//!
//! // Construct Basic Text literals.
//! let greeting = text!("Hello, World!");
//!
//! // Write Basic Text directly.
//! stream.write_text(greeting).unwrap();
//!
//! // `TextString` can't be split at arbitrary boundaries, so this crate has
//! // substring types, so you can work with Basic Text content incrementally.
//! // The following code prints the "Service Dog" ZWJ Sequence "🐕‍🦺" in
//! // parts, where splitting it would not be valid in Basic Text.
//! stream
//!     .write_text_substr(text_substr!("🐕\u{200d}"))
//!     .unwrap();
//! stream.write_text_substr(text_substr!("🦺")).unwrap();
//!
//! // Regular strings with Basic Text content can be written.
//! writeln!(stream, "Valid!").unwrap();
//!
//! // But invalid content is diagnosed as an error.
//! writeln!(stream, "\u{c}Invalid!\u{7}").unwrap_err();
//!
//! // A Basic Text reader, on the other hand, always succeeds, by replacing
//! // invalid sequences with `�`s.
//! let mut s = TextString::new();
//! TextReader::new(stdin())
//!     .read_to_text_string(&mut s)
//!     .unwrap();
//! ```
//!
//! [Basic Text]: https://github.com/sunfishcode/basic-text/blob/main/docs/BasicText.md#basic-text
//! [`text!("...")` macro]: crate::text
//! [`Duplex`]: https://docs.rs/duplex/latest/duplex/trait.Duplex.html
//! [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html
//! [`text_lines`]: https://docs.rs/basic-text/latest/basic_text/trait.BufReadText.html#method.text_lines
//! [`text_lines_lossy`]: https://docs.rs/basic-text/latest/basic_text/trait.BufReadText.html#method.text_lines_lossy

#![deny(missing_docs)]
#![cfg_attr(can_vector, feature(can_vector))]
#![cfg_attr(write_all_vectored, feature(write_all_vectored))]
#![cfg_attr(pattern, feature(pattern))]
#![cfg_attr(extend_one, feature(extend_one))]

mod buf_read_text;
mod copy;
mod partial_eq;
mod read_text;
mod text_duplexer;
mod text_input;
mod text_output;
mod text_reader;
mod text_string;
mod text_substring;
mod text_writer;
mod write_text;

pub use basic_text_internals::unicode::NORMALIZATION_BUFFER_SIZE;
pub use basic_text_internals::unicode_normalization::UNICODE_VERSION;
pub use basic_text_literals::{text, text_substr};
pub use buf_read_text::{BufReadText, TextLines, TextLinesLossy};
pub use copy::{copy_text, copy_text_using_status};
pub use read_text::{default_read_exact_text_substr, ReadText, ReadTextLayered};
pub use text_duplexer::TextDuplexer;
pub use text_reader::TextReader;
pub use text_string::{default_read_to_text_string, FromTextError, TextError, TextStr, TextString};
pub use text_substring::{TextSubstr, TextSubstring};
pub use text_writer::TextWriter;
pub use write_text::{default_write_text_substr, WriteText};