Expand description
A queue for a string.
§Summary
StrQueue is a queue for UTF-8 sequences.
Strings can be pushed into StrQueue, characters can be popped from the
queue, and the queue can be printed or converted into a string.
§Details
§Non-contiguous
StrQueue does not guarantee that the content is stored on a contiguous
memory region. As of writing this document, StrQueue internally uses a
ring buffer.
§Push
StrQueue accepts not only strings to be pushed, but also arbitrary bytes.
When bytes (including valid UTF-8 strings) are pushed, the things below
(theoretically) happen in order:
- Bytes are appended to the internal buffer.
- Internal buffers are validated.
- If the buffer has incomplete bytes at the end of the buffer,
they are preserved (at least the until the next bytes are added).
- “Incomplete bytes” here is byte sequence which can be valid UTF-8 sequence if appropriate bytes are appended.
- Other ill-formed bytes than that are replaced with
U+FFFD REPLACEMENT CHARACTERusing the same rule asString::from_utf8_lossy.
- If the buffer has incomplete bytes at the end of the buffer,
they are preserved (at least the until the next bytes are added).
§Pop
Pop operations are basically performed to characters, rather than raw bytes.
For example, StrQueue::pop_char pops the first character, not the first byte.
This principle helps the queue to keep the internal bytes valid as UTF-8 string.
§Conversion
When converting a queue into a string, caller can choose how to handle the
possible trailing incomplete bytes.
PartialHandling::Ignore lets methods ignore such incomplete bytes (if
exist), and PartialHandling::Emit lets methods emit them as a U+FFFD REPLACEMENT CHARACTER.
§Range
This crate provides adaptors for subrange access: BytesRange and
CharsRange. Subrange adaptor types plays a similar role as &str for
String: they are views to the subrange of the underlying StrQueue.
BytesRange can point to arbitrary subrange.
CharsRange can only point to a subrange that are valid UTF-8 string and
the last possibly incomplete character (i.e. the same condition as
StrQueue.
§Usage
§Creation
Default queue created by StrQueue::new is empty.
use str_queue::{PartialHandling, StrQueue};
let queue = StrQueue::new();
assert!(queue.display(PartialHandling::Emit).to_string().is_empty());A queue can be created with initial contents by StrQueue::from.
use str_queue::{PartialHandling, StrQueue};
let queue = StrQueue::from("hello");
assert_eq!(queue.display(PartialHandling::Emit).to_string(), "hello");use str_queue::{PartialHandling, StrQueue};
let queue = StrQueue::from(b"he\xf0llo\xce");
assert_eq!(queue.display(PartialHandling::Emit).to_string(), "he\u{FFFD}llo\u{FFFD}");§Push
Bytes and string can be pushed.
use str_queue::{PartialHandling, StrQueue};
let mut queue = StrQueue::new();
queue.push_str("hello");
assert_eq!(queue.display(PartialHandling::Emit).to_string(), "hello");
queue.push_bytes(b" world");
assert_eq!(queue.display(PartialHandling::Emit).to_string(), "hello world");§Pop
The first characters can be popped using StrQueue::pop_char.
use str_queue::StrQueue;
let mut queue = StrQueue::from(b"ab\xf0");
assert_eq!(queue.pop_char(), Some('a'));
assert_eq!(queue.pop_char(), Some('b'));
// Incomplete bytes are simply ignored as they are not a character.
assert_eq!(queue.pop_char(), None);The first line can be popped using StrQueue::pop_line.
use str_queue::StrQueue;
// Note that the last "world\r" is not considered as a complete line
// since the line can be finally "world\r" or "world\r\n".
let mut queue = StrQueue::from("Hello\nworld\r\nGoodbye\rworld\r");
// The popped line can be dropped.
queue.pop_line();
// The popped line can be accessed.
assert_eq!(queue.pop_line().map(|v| v.to_string()).as_deref(), Some("world\r\n"));
assert_eq!(queue.pop_line().map(|v| v.to_string()).as_deref(), Some("Goodbye\r"));
assert_eq!(queue.pop_line().map(|v| v.to_string()).as_deref(), None);
assert_eq!(queue.chars_range(..), "world\r");§Ranges
Bytes ranges can be created by StrQueue::bytes_range method.
use str_queue::StrQueue;
let queue = StrQueue::from("alpha\u{03B1}beta\u{03B2}");
let bytes = queue.bytes_range(6..12);
assert_eq!(bytes, b"\xb1beta\xce"[..]);Chars ranges can be created by StrQueue::chars_range method.
CharsRange implements Display and
ToString traits, since the it is guaranteed
to have a valid string as a prefix (with possibly incomplete character as
a suffix).
use str_queue::StrQueue;
let queue = StrQueue::from("alpha\u{03B1}beta\u{03B2}");
let range = queue.chars_range(7..);
assert_eq!(range, "beta\u{03B2}");
assert_eq!(range.to_string(), "beta\u{03B2}");Subranges can be created from ranges.
use str_queue::StrQueue;
let queue = StrQueue::from("Hello world");
let bytes = queue.bytes_range(6..);
assert_eq!(bytes, b"world"[..]);
let subrange = bytes.range(1..4);
assert_eq!(subrange, b"orl"[..]);use str_queue::StrQueue;
let queue = StrQueue::from("Hello world");
let range = queue.chars_range(6..);
assert_eq!(range, "world");
let subrange = range.range(1..4);
assert_eq!(subrange, "orl");§Conversion
Note that StrQueue does not guarantee the content is stored on a
contiguous memory region.
So, you cannot get the content string as a single &str without paying
additional cost.
§Display
StrQueue::display returns a helper struct which implements
core::fmt::Display. It can be written to a formatter or converted to
a string using .to_string().
To create String, use .to_string().
use str_queue::{PartialHandling, StrQueue};
let queue = StrQueue::from("hello");
let s: String = queue.display(PartialHandling::Emit).to_string();
assert_eq!(s, "hello");To write the string into a writer, use the return value directly.
use core::fmt::Write as _;
use str_queue::{PartialHandling, StrQueue};
let queue = StrQueue::from("hello");
// `String` implements `core::fmt::Write`, and can be used for `write!()`.
let mut buf = String::new();
write!(buf, "{}", queue.display(PartialHandling::Emit));
assert_eq!(buf, "hello");§Fragments
StrQueue::fragments returns an iterator of Fragments, which can hold
a substring slices and a characters.
use str_queue::{Fragment, PartialHandling, StrQueue};
// Note that `\xce` can appear as a first byte of valid UTF-8 sequence.
let queue = StrQueue::from(b"hello \xce");
let mut buf = String::new();
for frag in queue.fragments(PartialHandling::Emit) {
match frag {
Fragment::Str(s) => buf.push_str(s),
Fragment::Char(c) => buf.push(c),
Fragment::Incomplete => buf.push_str("<<incomplete>>"),
}
}
assert_eq!(buf, "hello <<incomplete>>");§Characters
StrQueue::chars and StrQueue::into_chars return an iterator of chars.
StrQueue::chars does not consume the queue.
use str_queue::{PartialHandling, StrQueue};
let queue = StrQueue::from("hello");
let mut chars = queue.chars(PartialHandling::Emit);
assert_eq!(chars.next(), Some('h'));
assert_eq!(chars.next(), Some('e'));
assert_eq!(chars.next(), Some('l'));
assert_eq!(chars.next(), Some('l'));
assert_eq!(chars.next(), Some('o'));
assert_eq!(chars.next(), None);
// `StrQueue::chars()` does not consume the queue, so it can be used here.
assert_eq!(
queue.chars(PartialHandling::Emit).collect::<String>(),
"hello"
);StrQueue::into_chars consumes the queue.
use str_queue::{PartialHandling, StrQueue};
let queue = StrQueue::from("hello");
let mut chars = queue.into_chars(PartialHandling::Emit);
assert_eq!(chars.next(), Some('h'));
assert_eq!(chars.next(), Some('e'));
assert_eq!(chars.next(), Some('l'));
assert_eq!(chars.next(), Some('l'));
assert_eq!(chars.next(), Some('o'));
assert_eq!(chars.next(), None);
// `queue` is no longer available, as it is consumeb dy `queue.into_chars()`.Structs§
- Bytes
Range - Subrange of a
StrQueue. - Chars
- Iterator of characters in a
StrQueue. - Chars
Range - Subrange of a
StrQueue. - Chars
Range Popped Line - A line popped from
CharsRangeusingpop_linemethod. - Display
- Helper struct for printing
StrQueue. - Fragments
- Iterator of content fragments of
StrQueue, created byStrQueue::fragments. - Into
Chars - Iterator of characters in a
StrQueue. - Popped
Fragment - A fragment popped from
StrQueueusingpop_fragmentmethod. - Popped
Line - A line popped from
StrQueueusingpop_linemethod. - StrQueue
- Queue for a string.
Enums§
- Fragment
- Content fragment of
StrQueue, emitted byFragmentsiterator. - Partial
Handling - Handling of suffix bytes of a partial (incomplete) character.