diff --git a/.cspell.dict/cpython.txt b/.cspell.dict/cpython.txt index 1840918a4..d28a4bb8c 100644 --- a/.cspell.dict/cpython.txt +++ b/.cspell.dict/cpython.txt @@ -17,6 +17,7 @@ elts excepthandler fileutils finalbody +formatfloat freevar freevars fromlist @@ -25,10 +26,12 @@ HIGHRES IMMUTABLETYPE kwonlyarg kwonlyargs +lasti linearise maxdepth mult nkwargs +noraise numer orelse pathconfig @@ -36,9 +39,12 @@ patma posonlyarg posonlyargs prec +preinitialized PYTHREAD_NAME SA_ONSTACK stackdepth +stringlib +structseq tok_oldval unaryop unparse diff --git a/.cspell.dict/python-more.txt b/.cspell.dict/python-more.txt index 0be3c0f45..040442832 100644 --- a/.cspell.dict/python-more.txt +++ b/.cspell.dict/python-more.txt @@ -16,6 +16,7 @@ baserepl basicsize bdfl bigcharset +bignum breakpointhook cformat chunksize @@ -153,6 +154,7 @@ ospath pendingcr phello platlibdir +popleft posixsubprocess posonly posonlyargcount diff --git a/.cspell.json b/.cspell.json index 69ace8348..98a03180f 100644 --- a/.cspell.json +++ b/.cspell.json @@ -105,9 +105,9 @@ "reducelib", "richcompare", "RustPython", + "significand", "struc", - // plural of summand - "summands", + "summands", // plural of summand "sysmodule", "tracebacks", "typealiases", diff --git a/common/src/boxvec.rs b/common/src/boxvec.rs index 450183547..f5dd622f5 100644 --- a/common/src/boxvec.rs +++ b/common/src/boxvec.rs @@ -1,4 +1,4 @@ -// cspell:ignore +// cspell:disable //! An unresizable vector backed by a `Box<[T]>` #![allow(clippy::needless_lifetimes)] diff --git a/common/src/linked_list.rs b/common/src/linked_list.rs index 83577b71d..4e6e1b700 100644 --- a/common/src/linked_list.rs +++ b/common/src/linked_list.rs @@ -1,3 +1,5 @@ +// cspell:disable + //! This module is modified from tokio::util::linked_list: //! Tokio is licensed under the MIT license: //! diff --git a/common/src/lock.rs b/common/src/lock.rs index 811c46111..ca5ffe8de 100644 --- a/common/src/lock.rs +++ b/common/src/lock.rs @@ -39,4 +39,4 @@ pub type PyMappedRwLockReadGuard<'a, T> = MappedRwLockReadGuard<'a, RawRwLock, T pub type PyRwLockWriteGuard<'a, T> = RwLockWriteGuard<'a, RawRwLock, T>; pub type PyMappedRwLockWriteGuard<'a, T> = MappedRwLockWriteGuard<'a, RawRwLock, T>; -// can add fn const_{mutex,rwlock}() if necessary, but we probably won't need to +// can add fn const_{mutex,rw_lock}() if necessary, but we probably won't need to diff --git a/compiler/codegen/src/compile.rs b/compiler/codegen/src/compile.rs index c8474a537..3c92146c1 100644 --- a/compiler/codegen/src/compile.rs +++ b/compiler/codegen/src/compile.rs @@ -2143,8 +2143,8 @@ impl Compiler<'_> { attrs: &[Identifier], _patterns: &[Pattern], ) -> CompileResult<()> { - let nattrs = attrs.len(); - for i in 0..nattrs { + let n_attrs = attrs.len(); + for i in 0..n_attrs { let attr = attrs[i].as_str(); // Check if the attribute name is forbidden in a Store context. if self.forbidden_name(attr, NameUsage::Store)? { @@ -2152,7 +2152,7 @@ impl Compiler<'_> { return Err(self.compile_error_forbidden_name(attr)); } // Check for duplicates: compare with every subsequent attribute. - for ident in attrs.iter().take(nattrs).skip(i + 1) { + for ident in attrs.iter().take(n_attrs).skip(i + 1) { let other = ident.as_str(); if attr == other { todo!(); @@ -2184,20 +2184,20 @@ impl Compiler<'_> { } let nargs = patterns.len(); - let nattrs = kwd_attrs.len(); + let n_attrs = kwd_attrs.len(); let nkwd_patterns = kwd_patterns.len(); // Validate that keyword attribute names and patterns match in length. - if nattrs != nkwd_patterns { + if n_attrs != nkwd_patterns { let msg = format!( "kwd_attrs ({}) / kwd_patterns ({}) length mismatch in class pattern", - nattrs, nkwd_patterns + n_attrs, nkwd_patterns ); unreachable!("{}", msg); } // Check for too many sub-patterns. - if nargs > u32::MAX as usize || (nargs + nattrs).saturating_sub(1) > i32::MAX as usize { + if nargs > u32::MAX as usize || (nargs + n_attrs).saturating_sub(1) > i32::MAX as usize { let msg = format!( "too many sub-patterns in class pattern {:?}", match_class.cls @@ -2207,7 +2207,7 @@ impl Compiler<'_> { } // Validate keyword attributes if any. - if nattrs != 0 { + if n_attrs != 0 { self.validate_kwd_attrs(&kwd_attrs, &kwd_patterns)?; } @@ -2237,12 +2237,12 @@ impl Compiler<'_> { // 5. Compare with IS_OP 1. emit!(self, Instruction::IsOperation(true)); - // At this point the TOS is a tuple of (nargs + nattrs) attributes (or None). + // At this point the TOS is a tuple of (nargs + n_attrs) attributes (or None). pc.on_top += 1; self.jump_to_fail_pop(pc, JumpOp::PopJumpIfFalse)?; - // Unpack the tuple into (nargs + nattrs) items. - let total = nargs + nattrs; + // Unpack the tuple into (nargs + n_attrs) items. + let total = nargs + n_attrs; emit!( self, Instruction::UnpackSequence { @@ -2280,12 +2280,12 @@ impl Compiler<'_> { // let keys = &mapping.keys; // let patterns = &mapping.patterns; // let size = keys.len(); - // let npatterns = patterns.len(); + // let n_patterns = patterns.len(); - // if size != npatterns { - // panic!("keys ({}) / patterns ({}) length mismatch in mapping pattern", size, npatterns); + // if size != n_patterns { + // panic!("keys ({}) / patterns ({}) length mismatch in mapping pattern", size, n_patterns); // // return self.compiler_error( - // // &format!("keys ({}) / patterns ({}) length mismatch in mapping pattern", size, npatterns) + // // &format!("keys ({}) / patterns ({}) length mismatch in mapping pattern", size, n_patterns) // // ); // } diff --git a/src/lib.rs b/src/lib.rs index 98de3de5c..e9c9c9129 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -233,14 +233,14 @@ fn write_profile(settings: &Settings) -> Result<(), Box> enum ProfileFormat { Html, Text, - SpeedScore, + SpeedScope, } let profile_output = settings.profile_output.as_deref(); let profile_format = match settings.profile_format.as_deref() { Some("html") => ProfileFormat::Html, Some("text") => ProfileFormat::Text, None if profile_output == Some("-".as_ref()) => ProfileFormat::Text, - Some("speedscope") | None => ProfileFormat::SpeedScore, + Some("speedscope") | None => ProfileFormat::SpeedScope, Some(other) => { error!("Unknown profile format {}", other); // TODO: Need to change to ExitCode or Termination @@ -251,7 +251,7 @@ fn write_profile(settings: &Settings) -> Result<(), Box> let profile_output = profile_output.unwrap_or_else(|| match profile_format { ProfileFormat::Html => "flame-graph.html".as_ref(), ProfileFormat::Text => "flame.txt".as_ref(), - ProfileFormat::SpeedScore => "flamescope.json".as_ref(), + ProfileFormat::SpeedScope => "flamescope.json".as_ref(), }); let profile_output: Box = if profile_output == "-" { @@ -265,7 +265,7 @@ fn write_profile(settings: &Settings) -> Result<(), Box> match profile_format { ProfileFormat::Html => flame::dump_html(profile_output)?, ProfileFormat::Text => flame::dump_text_to_writer(profile_output)?, - ProfileFormat::SpeedScore => flamescope::dump(profile_output)?, + ProfileFormat::SpeedScope => flamescope::dump(profile_output)?, } Ok(()) diff --git a/stdlib/src/binascii.rs b/stdlib/src/binascii.rs index a8df1fb60..2510325b4 100644 --- a/stdlib/src/binascii.rs +++ b/stdlib/src/binascii.rs @@ -1,4 +1,4 @@ -// spell-checker:ignore hexlify unhexlify uuencodes CRCTAB +// spell-checker:ignore hexlify unhexlify uuencodes CRCTAB rlecode rledecode pub(super) use decl::crc32; pub(crate) use decl::make_module; @@ -328,7 +328,7 @@ mod decl { idx += 1; } } else if buffer[idx] == b'=' { - // roken case from broken python qp + // broken case from broken python qp out_data.push(b'='); idx += 1; } else if idx + 1 < len @@ -382,183 +382,184 @@ mod decl { let header = args.header; s.with_ref(|buf| { let buflen = buf.len(); - let mut linelen = 0; - let mut odatalen = 0; + let mut line_len = 0; + let mut out_data_len = 0; let mut crlf = false; let mut ch; - let mut inidx; - let mut outidx; + let mut in_idx; + let mut out_idx; - inidx = 0; - while inidx < buflen { - if buf[inidx] == b'\n' { + in_idx = 0; + while in_idx < buflen { + if buf[in_idx] == b'\n' { break; } - inidx += 1; + in_idx += 1; } - if buflen > 0 && inidx < buflen && buf[inidx - 1] == b'\r' { + if buflen > 0 && in_idx < buflen && buf[in_idx - 1] == b'\r' { crlf = true; } - inidx = 0; - while inidx < buflen { + in_idx = 0; + while in_idx < buflen { let mut delta = 0; - if (buf[inidx] > 126) - || (buf[inidx] == b'=') - || (header && buf[inidx] == b'_') - || (buf[inidx] == b'.' - && linelen == 0 - && (inidx + 1 == buflen - || buf[inidx + 1] == b'\n' - || buf[inidx + 1] == b'\r' - || buf[inidx + 1] == 0)) - || (!istext && ((buf[inidx] == b'\r') || (buf[inidx] == b'\n'))) - || ((buf[inidx] == b'\t' || buf[inidx] == b' ') && (inidx + 1 == buflen)) - || ((buf[inidx] < 33) - && (buf[inidx] != b'\r') - && (buf[inidx] != b'\n') - && (quotetabs || ((buf[inidx] != b'\t') && (buf[inidx] != b' ')))) + if (buf[in_idx] > 126) + || (buf[in_idx] == b'=') + || (header && buf[in_idx] == b'_') + || (buf[in_idx] == b'.' + && line_len == 0 + && (in_idx + 1 == buflen + || buf[in_idx + 1] == b'\n' + || buf[in_idx + 1] == b'\r' + || buf[in_idx + 1] == 0)) + || (!istext && ((buf[in_idx] == b'\r') || (buf[in_idx] == b'\n'))) + || ((buf[in_idx] == b'\t' || buf[in_idx] == b' ') && (in_idx + 1 == buflen)) + || ((buf[in_idx] < 33) + && (buf[in_idx] != b'\r') + && (buf[in_idx] != b'\n') + && (quotetabs || ((buf[in_idx] != b'\t') && (buf[in_idx] != b' ')))) { - if (linelen + 3) >= MAXLINESIZE { - linelen = 0; + if (line_len + 3) >= MAXLINESIZE { + line_len = 0; delta += if crlf { 3 } else { 2 }; } - linelen += 3; + line_len += 3; delta += 3; - inidx += 1; + in_idx += 1; } else if istext - && ((buf[inidx] == b'\n') - || ((inidx + 1 < buflen) - && (buf[inidx] == b'\r') - && (buf[inidx + 1] == b'\n'))) + && ((buf[in_idx] == b'\n') + || ((in_idx + 1 < buflen) + && (buf[in_idx] == b'\r') + && (buf[in_idx + 1] == b'\n'))) { - linelen = 0; + line_len = 0; // Protect against whitespace on end of line - if (inidx != 0) && ((buf[inidx - 1] == b' ') || (buf[inidx - 1] == b'\t')) { + if (in_idx != 0) && ((buf[in_idx - 1] == b' ') || (buf[in_idx - 1] == b'\t')) { delta += 2; } delta += if crlf { 2 } else { 1 }; - inidx += if buf[inidx] == b'\r' { 2 } else { 1 }; + in_idx += if buf[in_idx] == b'\r' { 2 } else { 1 }; } else { - if (inidx + 1 != buflen) - && (buf[inidx + 1] != b'\n') - && (linelen + 1) >= MAXLINESIZE + if (in_idx + 1 != buflen) + && (buf[in_idx + 1] != b'\n') + && (line_len + 1) >= MAXLINESIZE { - linelen = 0; + line_len = 0; delta += if crlf { 3 } else { 2 }; } - linelen += 1; + line_len += 1; delta += 1; - inidx += 1; + in_idx += 1; } - odatalen += delta; + out_data_len += delta; } - let mut out_data = Vec::with_capacity(odatalen); - inidx = 0; - outidx = 0; - linelen = 0; + let mut out_data = Vec::with_capacity(out_data_len); + in_idx = 0; + out_idx = 0; + line_len = 0; - while inidx < buflen { - if (buf[inidx] > 126) - || (buf[inidx] == b'=') - || (header && buf[inidx] == b'_') - || ((buf[inidx] == b'.') - && (linelen == 0) - && (inidx + 1 == buflen - || buf[inidx + 1] == b'\n' - || buf[inidx + 1] == b'\r' - || buf[inidx + 1] == 0)) - || (!istext && ((buf[inidx] == b'\r') || (buf[inidx] == b'\n'))) - || ((buf[inidx] == b'\t' || buf[inidx] == b' ') && (inidx + 1 == buflen)) - || ((buf[inidx] < 33) - && (buf[inidx] != b'\r') - && (buf[inidx] != b'\n') - && (quotetabs || ((buf[inidx] != b'\t') && (buf[inidx] != b' ')))) + while in_idx < buflen { + if (buf[in_idx] > 126) + || (buf[in_idx] == b'=') + || (header && buf[in_idx] == b'_') + || ((buf[in_idx] == b'.') + && (line_len == 0) + && (in_idx + 1 == buflen + || buf[in_idx + 1] == b'\n' + || buf[in_idx + 1] == b'\r' + || buf[in_idx + 1] == 0)) + || (!istext && ((buf[in_idx] == b'\r') || (buf[in_idx] == b'\n'))) + || ((buf[in_idx] == b'\t' || buf[in_idx] == b' ') && (in_idx + 1 == buflen)) + || ((buf[in_idx] < 33) + && (buf[in_idx] != b'\r') + && (buf[in_idx] != b'\n') + && (quotetabs || ((buf[in_idx] != b'\t') && (buf[in_idx] != b' ')))) { - if (linelen + 3) >= MAXLINESIZE { + if (line_len + 3) >= MAXLINESIZE { // MAXLINESIZE = 76 out_data.push(b'='); - outidx += 1; + out_idx += 1; if crlf { out_data.push(b'\r'); - outidx += 1; + out_idx += 1; } out_data.push(b'\n'); - outidx += 1; - linelen = 0; + out_idx += 1; + line_len = 0; } out_data.push(b'='); - outidx += 1; + out_idx += 1; - ch = hex_nibble(buf[inidx] >> 4); + ch = hex_nibble(buf[in_idx] >> 4); if (b'a'..=b'f').contains(&ch) { ch -= b' '; } out_data.push(ch); - ch = hex_nibble(buf[inidx] & 0xf); + ch = hex_nibble(buf[in_idx] & 0xf); if (b'a'..=b'f').contains(&ch) { ch -= b' '; } out_data.push(ch); - outidx += 2; - inidx += 1; - linelen += 3; + out_idx += 2; + in_idx += 1; + line_len += 3; } else if istext - && ((buf[inidx] == b'\n') - || ((inidx + 1 < buflen) - && (buf[inidx] == b'\r') - && (buf[inidx + 1] == b'\n'))) + && ((buf[in_idx] == b'\n') + || ((in_idx + 1 < buflen) + && (buf[in_idx] == b'\r') + && (buf[in_idx + 1] == b'\n'))) { - linelen = 0; - if (outidx != 0) - && ((out_data[outidx - 1] == b' ') || (out_data[outidx - 1] == b'\t')) + line_len = 0; + if (out_idx != 0) + && ((out_data[out_idx - 1] == b' ') || (out_data[out_idx - 1] == b'\t')) { - ch = hex_nibble(out_data[outidx - 1] >> 4); + ch = hex_nibble(out_data[out_idx - 1] >> 4); if (b'a'..=b'f').contains(&ch) { ch -= b' '; } out_data.push(ch); - ch = hex_nibble(out_data[outidx - 1] & 0xf); + ch = hex_nibble(out_data[out_idx - 1] & 0xf); if (b'a'..=b'f').contains(&ch) { ch -= b' '; } out_data.push(ch); - out_data[outidx - 1] = b'='; - outidx += 2; + out_data[out_idx - 1] = b'='; + out_idx += 2; } if crlf { out_data.push(b'\r'); - outidx += 1; + out_idx += 1; } out_data.push(b'\n'); - outidx += 1; - inidx += if buf[inidx] == b'\r' { 2 } else { 1 }; + out_idx += 1; + in_idx += if buf[in_idx] == b'\r' { 2 } else { 1 }; } else { - if (inidx + 1 != buflen) && (buf[inidx + 1] != b'\n') && (linelen + 1) >= 76 { + if (in_idx + 1 != buflen) && (buf[in_idx + 1] != b'\n') && (line_len + 1) >= 76 + { // MAXLINESIZE = 76 out_data.push(b'='); - outidx += 1; + out_idx += 1; if crlf { out_data.push(b'\r'); - outidx += 1; + out_idx += 1; } out_data.push(b'\n'); - outidx += 1; - linelen = 0; + out_idx += 1; + line_len = 0; } - linelen += 1; - if header && buf[inidx] == b' ' { + line_len += 1; + if header && buf[in_idx] == b' ' { out_data.push(b'_'); - outidx += 1; - inidx += 1; + out_idx += 1; + in_idx += 1; } else { - out_data.push(buf[inidx]); - outidx += 1; - inidx += 1; + out_data.push(buf[in_idx]); + out_idx += 1; + in_idx += 1; } } } @@ -568,7 +569,7 @@ mod decl { #[pyfunction] fn rlecode_hqx(s: ArgAsciiBuffer) -> PyResult> { - const RUNCHAR: u8 = 0x90; // b'\x90' + const RUN_CHAR: u8 = 0x90; // b'\x90' s.with_ref(|buffer| { let len = buffer.len(); let mut out_data = Vec::::with_capacity((len * 2) + 2); @@ -577,20 +578,20 @@ mod decl { while idx < len { let ch = buffer[idx]; - if ch == RUNCHAR { - out_data.push(RUNCHAR); + if ch == RUN_CHAR { + out_data.push(RUN_CHAR); out_data.push(0); return Ok(out_data); } else { - let mut inend = idx + 1; - while inend < len && buffer[inend] == ch && inend < idx + 255 { - inend += 1; + let mut in_end = idx + 1; + while in_end < len && buffer[in_end] == ch && in_end < idx + 255 { + in_end += 1; } - if inend - idx > 3 { + if in_end - idx > 3 { out_data.push(ch); - out_data.push(RUNCHAR); - out_data.push(((inend - idx) % 256) as u8); - idx = inend - 1; + out_data.push(RUN_CHAR); + out_data.push(((in_end - idx) % 256) as u8); + idx = in_end - 1; } else { out_data.push(ch); } @@ -603,7 +604,7 @@ mod decl { #[pyfunction] fn rledecode_hqx(s: ArgAsciiBuffer) -> PyResult> { - const RUNCHAR: u8 = 0x90; //b'\x90' + const RUN_CHAR: u8 = 0x90; //b'\x90' s.with_ref(|buffer| { let len = buffer.len(); let mut out_data = Vec::::with_capacity(len); @@ -613,9 +614,9 @@ mod decl { idx += 1; while idx < len { - if buffer[idx] == RUNCHAR { + if buffer[idx] == RUN_CHAR { if buffer[idx + 1] == 0 { - out_data.push(RUNCHAR); + out_data.push(RUN_CHAR); } else { let ch = buffer[idx - 1]; let range = buffer[idx + 1]; diff --git a/stdlib/src/syslog.rs b/stdlib/src/syslog.rs index 69e9d1cb9..dcdf317b0 100644 --- a/stdlib/src/syslog.rs +++ b/stdlib/src/syslog.rs @@ -1,4 +1,4 @@ -// spell-checker:ignore logoption openlog setlogmask upto NDELAY +// spell-checker:ignore logoption openlog setlogmask upto NDELAY ODELAY pub(crate) use syslog::make_module; diff --git a/vm/src/buffer.rs b/vm/src/buffer.rs index 3b76002d0..a07048757 100644 --- a/vm/src/buffer.rs +++ b/vm/src/buffer.rs @@ -453,7 +453,7 @@ trait PackInt: PrimInt { fn unpack_int(data: &[u8]) -> Self; } -macro_rules! make_pack_primint { +macro_rules! make_pack_prim_int { ($T:ty) => { impl PackInt for $T { fn pack_int(self, data: &mut [u8]) { @@ -502,16 +502,16 @@ where .map_err(|_| new_struct_error(vm, "argument out of range".to_owned())) } -make_pack_primint!(i8); -make_pack_primint!(u8); -make_pack_primint!(i16); -make_pack_primint!(u16); -make_pack_primint!(i32); -make_pack_primint!(u32); -make_pack_primint!(i64); -make_pack_primint!(u64); -make_pack_primint!(usize); -make_pack_primint!(isize); +make_pack_prim_int!(i8); +make_pack_prim_int!(u8); +make_pack_prim_int!(i16); +make_pack_prim_int!(u16); +make_pack_prim_int!(i32); +make_pack_prim_int!(u32); +make_pack_prim_int!(i64); +make_pack_prim_int!(u64); +make_pack_prim_int!(usize); +make_pack_prim_int!(isize); macro_rules! make_pack_float { ($T:ty) => { diff --git a/vm/src/builtins/type.rs b/vm/src/builtins/type.rs index a0c7ee58f..7351797de 100644 --- a/vm/src/builtins/type.rs +++ b/vm/src/builtins/type.rs @@ -489,7 +489,7 @@ impl PyType { #[pygetset(setter, name = "__bases__")] fn set_bases(zelf: &Py, bases: Vec, vm: &VirtualMachine) -> PyResult<()> { // TODO: Assigning to __bases__ is only used in typing.NamedTupleMeta.__new__ - // Rather than correctly reinitializing the class, we are skipping a few steps for now + // Rather than correctly re-initializing the class, we are skipping a few steps for now if zelf.slots.flags.has_feature(PyTypeFlags::IMMUTABLETYPE) { return Err(vm.new_type_error(format!( "cannot set '__bases__' attribute of immutable type '{}'", diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index 708a93fe6..6c4f97fe3 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -211,9 +211,9 @@ impl VirtualMachine { if let Some(text) = maybe_text { // if text ends with \n, remove it - let rtext = text.as_str().trim_end_matches('\n'); - let l_text = rtext.trim_start_matches([' ', '\n', '\x0c']); // \x0c is \f - let spaces = (rtext.len() - l_text.len()) as isize; + let r_text = text.as_str().trim_end_matches('\n'); + let l_text = r_text.trim_start_matches([' ', '\n', '\x0c']); // \x0c is \f + let spaces = (r_text.len() - l_text.len()) as isize; writeln!(output, " {}", l_text)?; diff --git a/wtf8/src/core_char.rs b/wtf8/src/core_char.rs index 1444e8e13..e2400430c 100644 --- a/wtf8/src/core_char.rs +++ b/wtf8/src/core_char.rs @@ -1,3 +1,4 @@ +// cspell:disable //! Unstable functions from [`core::char`] use core::slice; diff --git a/wtf8/src/core_str_count.rs b/wtf8/src/core_str_count.rs index cff5a4b07..30fcd4645 100644 --- a/wtf8/src/core_str_count.rs +++ b/wtf8/src/core_str_count.rs @@ -1,3 +1,4 @@ +// cspell:disable //! Modified from core::str::count use super::Wtf8; diff --git a/wtf8/src/lib.rs b/wtf8/src/lib.rs index 73b516845..635ddf353 100644 --- a/wtf8/src/lib.rs +++ b/wtf8/src/lib.rs @@ -1,3 +1,5 @@ +// cspell:disable + //! An implementation of [WTF-8], a utf8-compatible encoding that allows for //! unpaired surrogate codepoints. This implementation additionally allows for //! paired surrogates that are nonetheless treated as two separate codepoints.