1 line
589 KiB
Plaintext
1 line
589 KiB
Plaintext
'/// This is an implementation of a general purpose skip list. It was originallyn/// ported from a version of skiplists intended for efficient string handlingn/// found here - https://github.com/josephg/rustropenn/// This implementation is not optimized for strings (there's some stringn/// specific features like unicode handling which have been intentionallyn/// removed for simplicity). But it does have another somewhat unusual feature -n/// users can specify their own size function, and lookups, inserts and deletesn/// can use their custom length property to specify offsets.''nn/// Unlike other rust rope implementations, this implementation should be veryn/// fast; but it manages that through heavy use of unsafe pointers and C-stylen/// dynamic arrays.nnuse std::{mem, ptr}''use std::mem::MaybeUninit;nuse std::ptr::NonNull;nuse std::alloc::{alloc, dealloc, Layout};nuse std::cmp::min;nuse std::marker::PhantomData;nuse std::iter;nnuse std::fmt;nnuse rand::{RngCore, Rng, SeedableRng};nuse rand::rngs::SmallRng;nn/// The likelyhood a node will have height (n'2'+1) instead of nnconst BIAS: u8 = 100; // out of 256.nn/// The number of it''''t's'i'L'ems in each node. Must fit in a u8 thanks to Node.n#[cfg(debug_assertions)]nconst NODE_NUM_ITEMS: usize ='10''2''10''2'''0'1''''1''''2' 10;nn#[cfg(not(debug_assertions))]nconst NODE_NUM_ITEMS: usize = 100;nn/// Rope operations will move to linear time after NODE_STR_SIZE * 2 ^n/// MAX_HEIGHT length. (With a smaller constant the higher this is). On the flipn/// side, cursors grow linearly with this number; so smaller is marginallyn/// better when the''''m'e't'I''''V''''T''''I''''I''' conten''''m'e''''m'e't't'I'''t''s'' ''a''r''e sm'I'''aller.n#[cfg(debug_assertions)]nco'5''2'nst MAX_HEIGHT: usize = 5;'m'n'e'n't'#'I'[cf''g('V'not''('m'd'e'''t'T'ebu''g_'I'ass''ertions'I'))]''nconst MAX_H'm'E'e''I''''m'I't'e''G''t'I'H'I'T:''m'' u'e'''s't'i'''V'ze ='''' 10;''m'T'''n'e'nnc'''t'''on'm'''I'I'e''st'''t' M''''AX_HE'V'IGHT_U8: '''I'u8''T'''''''''''''''''I'I'''''''Par'''m'tia'e'lE''t'''''I'''m'I'q']'''m''e'E''''e''' 't'''t',''>'I'I'''''''')'''q'm'''''m'''p'e'u''m'V'e''t''''b(su'e't''pe'm'r''''''I't''e') ''T''''I''t'''''''i't'''r''V'''a'''I''P'('e'''''v'i'''r''T'e'd'''['#'n''' ''''= MAX_'''I'''''I'''impl<Item: ListItem> Default for ItemMarker<Item> {n fn default() -> Self { Self::null() }n}nn'''''I'''''''''''C''''''':':'t'm'f''''''g'u'b'e'D'l''on'''''''''''''''''''''''''''''':':'t'm'f''''''''''''t'm'f'''''':':'d'''':'t's''''''''''''''''''''' '''''''''''''''''''''';')'''r'e'k'r'a'M'm'e't'I'''('d'a'p'.'f' ''' }''n 'n ' '{' 't'l'u's'e'R' '>'-' ')'>''''''_'''<'r'e't't'a'm'r'o'F' 't'u'm'&' ':'f' ','f'l'e's'&'('t'm'f' 'n'f'''''''']''I''')'y'p''m'o'C' '''I''e''m'''m'' ','e't''e''''e''I'''C'''t''''''''l'p'm'i''''//! Utilities for formatting and pr'' /// An optimized method to calculate the userlen of a slice of ListItems.n /// The default implementation simply calls [`get_usersize`] in a loop.'' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'p'o'o''n ''''''''''''''''''''d'e's's'a'p'''''''''''''''''''''''''''''''''''''''''''.'t'e's'&''''f'f'o' 'd'e'i'f'i'c'e'p's' 'e'm''n '// ' fn split_item(self, _at: usize) -> (Self, Self) {'o's' '''''''''''''s' 'a'''''''''''''p's' 'a' 't'a' ''''''''''''''''''s'm'e't'i' 'f'o' 'r'i'a'p' 'a' 'o't'''''''a' 'n'i'''t'a' 'm'e't'i' 'd'e'm'a'n''''e'p's' 'e'h't' 't'i'l'p'S' '/'/'/' 'l' 'a' 'n'i' ']'`'e'z'i's'r'e's'u'_'t'e'g'`'[''''g' 's'l'l'a'c' 'y'l'p'm'i's' 'n'o'i't'a't'n'e'm'e'l'p'm'i' 't'l'u'a'f'e'd' 'e'h'T' '.'s'm'e't'I't's'i'L' 'f'o' 'e'c'i'l's' 'a' 'f'o' 'n'e'l'r'e's'u' 'e'h't' 'e't'a'l'u'c'l'a'c' 'o't' 'd'o'h't'e'm''''r'e'v' 'd'e'z'i'm'i't'p'o' 'n'A'''''''''g'n'e'l'''''r'e's'u' 'e'h'T' ''''''' '/'/'/'/''' '''''''''/'/'/' ''''''''''/'/'/'''n 'inting strings.nn#![stable(feature = 'rust1', since = '1.0.0')]nnuse crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};nuse crate::marker::PhantomData;nuse crate::mem;nuse crate::num::flt2dec;nuse crate::ops::Deref;nuse crate::result;nuse crate::str;nnmod builders;nmod float;nmod num;nn#[stable(feature = 'fmt_flag'''''''''''m'o'r'f'_'e'g'r'e'''''n'm' ''''_'y'r'_into''''''t''''' ''''''''y'r'T' '/'/' '''_'' '' // fn merge_into(&mut self, other: &Self) -'''n '''''e's'l'a'f' ''' }'n '{' '''> bool'''''''n '// ' ';''''''''e'''g'r'e'm'_'n'a'n''n''c'' ''n '// '''''''''''''''''o'''''''''''''''''n '// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''/'/';'>'''')'f'l'e'S'<'n'o'i't'p'O' '>'-' ')'f'l'e's'&' ':'r'e'h't'o' ','f'l'e's'&'('e'g'r'e'm'_'y'r't' 'n'f' '''''''n ';'f'l'e'S' '>''''''''''S' '.'-' ')''''''f'l'e'S' ':'r'e'h't'i'''''''h't' ','f'l'e's''''&'('e'g'r'e'm' 'n'f' '// '''''''''''''''''''''''''''''''''''''''''''''''';'l'o'o'b' '>'-''''-' ')'f'l''''''''''f'l'p'e'S'&' ':'r'e'h't'o' ','f'l'e's' 't'u'm'&'('o't'n'i'_'e'g'r'e'm' 'n'f' 'n ' 's_align', since = '1.28.0')]n/// Possible alignments returned by `Formatter::align`n#[derive(Debug)]npub enum Alignment {n #[stable(feature = 'fmt_flags_align', since = '1.28.0')]n /// Indication that contents should be left-aligned.n Left,n #[stable(feature = 'fmt_flags_align', since = '1.28.0')]n /// Indication that contents should be right-aligned.n Right,n #[stable(feature = 'fmt_flags_align', since = '1.28.0')]n /// Indication that contents should be center-a''''l'o'o'b'ligne'nimpl Li''''r'a'''h'c'stItem for u8 {'n'}''nimpl ListItem for u8 {}'d.n Center,n}nn#[stable(feature = 'debug_builders', since = '1.2.0')]npub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};nn#[unstable(feature = 'fmt_internals', reason 'impl ListItem for'&' bool {}nimpl ListItem f'&'or char {''}n''n'= 'internal to format_args!', issue = 'none')]n#[doc(hidden)]npub mod rt {n pub mod v1;n}nn/// The type returned by formatter methods.n///n/// # Examplesn///n/// ```n/// use std::fmt;n///n/// #[derive(Debug)]n/// struct Triangle {n/// a: f32,n/// b: f32,n/// c: f32n/// }n///n/// impl fmt::Display for Triangle {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// write!(f, '({}, {}, {})', self.a, self.b, self.c)n/// }n/// }n///n/// let pythagorean_triple = Triangle { a: 3.0, b: 4.0, c: 5.0 };n///n/// assert_eq!(format!('{}', pythagorean_triple), '(3, 4, 5)');n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]npub type Result = result::Result<(), Error>;nn/// The error type which is returned from formatting a message into a stream.n///n/// This type does not support transmission of an error other than that an errorn/// occurred. Any extra information must be arranged to be transmitted throughn/// some other means.n///n/// An important thing to remember is that the type `fmt::Error` should not ben/// confused with [`std::io::Error`] or [`std::error::Error`], which you may alson/// have in scope.n///n/// [`std::io::Error`]: ../../std/io/struct.Error.htmln/// [`std::error::Error`]: ../../std/error/trait.Error.htmln///n/// # Examplesn///n/// ```rustn/// use std::fmt::{self, write};n///n/// let mut output = String::new();n/// if let Err(fmt::Error) = write(&mut output, format_args!('Hello {}!', 'world')) {n/// panic!('An error occurred');n/// }n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]n#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]npub struct Error;nn/// A collection of methods that are required to format a message into a stream.n///n/// This trait is the type which this modules requires when formattingn/// information. This is similar to the standard library's [`io::Write`] trait,n/// but it is only intended for use in libcore.n///n/// This trait should generally not be implemented by consumers of the standardn/// library. The [`write!`] macro accepts an instance of [`io::Write`], and then/// [`io::Write`] trait is favored over implementing this trait.n///n/// [`write!`]: ../../std/macro.write.htmln/// [`io::Write`]: ../../std/io/trait.Write.htmln#[stable(feature = 'rust1', since = '1.0.0')]npub trait Write {n /// Writes a string slice into this writer, returning whether the writen /// succeeded.n ///n /// This method can only succeed if the entire string slice was successfullyn /// written, and this method will not return until all data has beenn /// written or an error occurs.n ///n /// # Errorsn ///n /// This function will return an instance of [`Error`] on error.n ///n /// [`Error`]: struct.Error.htmln ///n /// # Examplesn ///n /// ```n /// use std::fmt::{Error, Write};n ///n /// fn writer<W: Write>(f: &mut W, s: &str) -> Result<(), Error> {n /// f.write_str(s)n /// }n ///n /// let mut buf = String::new();n /// writer(&mut buf, 'hola').unwrap();n /// assert_eq!(&buf, 'hola');n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n fn write_str(&mut self, s: &str) -> Result;nn /// Writes a [`char`] into this writer, returning whether the write succeeded.n ///n /// A single [`char`] may be encoded as more than one byte.n /// This method can only succeed if the entire byte sequence was successfullyn /// written, and this method will not return until all data has beenn /// written or an error occurs.n ///n /// # Errorsn ///n /// This function will return an instance of [`Error`] on error.n ///n /// [`char`]: ../../std/primitive.char.htmln /// [`Error`]: struct.Error.htmln ///n /// # Examplesn ///n /// ```n /// use std::fmt::{Error, Write};n ///n /// fn writer<W: Write>(f: &mut W, c: char) -> Result<(), Error> {n /// f.write_char(c)n /// }n ///n /// let mut buf = String::new();n /// writer(&mut buf, 'a').unwrap();n /// writer(&mut buf, 'b').unwrap();n /// assert_eq!(&buf, 'ab');n /// ```n #[stable(feature = 'fmt_write_char', since = '1.1.0')]n fn write_char(&mut self, c: char) -> Result {n self.write_str(c.encode_utf8(&mut [0; 4]))n }nn /// Glue for usage of the [`write!`] macro with implementors of this trait.n ///n /// This method should generally not be invoked manually, but rather throughn /// the [`write!`] macro itself.n ///n /// [`write!`]: ../../std/macro.write.htmln ///n /// # Examplesn ///n /// ```n /// use std::fmt::{Error, Write};n ///n /// fn writer<W: Write>(f: &mut W, s: &str) -> Result<(), Error> {n /// f.write_fmt(format_args!('{}', s))n /// }n ///n /// let mut buf = String::new();n /// writer(&mut buf, 'world').unwrap();n /// assert_eq!(&buf, 'world');n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n fn write_fmt(mut self: &mut Self, args: Arguments<'_>) -> Result {n write(&mut self, args)n }n}nn#[stable(feature = 'fmt_write_blanket_impl', since = '1.4.0')]nimpl<W: Write + ?Sized> Write for &mut W {n fn write_str(&mut self, s: &str) -> Result {n (**self).write_str(s)n }nn fn write_char(&mut self, c: char) -> Result {n (**self).write_char(c)n }nn fn write_fmt(&mut self, args: Arguments<'_>) -> Result {n (**self).write_fmt(args)n }n}nn/// Configuration for formatting.n///n/// A `Formatter` represents various options related to formatting. Users do notn/// construct `Formatter`s directly; a mutable reference to one is passed ton/// the `fmt` method of all formatting traits, like [`Debug`] and [`Display`].n///n/// To interact with a `Formatter`, you'll call various methods to change then/// various options related to formatting. For examples, please see then/// documentation of the methods defined on `Formatter` below.n///n/// [`Debug`]: trait.Debug.htmln/// [`Display`]: trait.Display.htmln#[allow(missing_debug_implementations)]n#[stable(feature = 'rust1', since = '1.0.0')]npub struct Formatter<'a> {n flags: u32,n fill: char,n align: rt::v1::Alignment,n width: Option<usize>,n precision: Option<usize>,nn buf: &'a mut (dyn Write + 'a),n}nn// NB. Argument is essentially an optimized partially applied formatting function,n// equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`.nnextern 'C' {n type Opaque;n}nn/// This struct represents the generic 'argument' which is taken by the Xprintfn/// family of functions. It contains a function to format the given value. Atn/// compile time it is ensured that the function and the value have the correctn/// types, and then this struct is used to canonicalize arguments to one type.n#[derive(Copy, Clone)]n#[allow(missing_debug_implementations)]n#[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]n#[doc(hidden)]npub struct ArgumentV1<'a> {n value: &'a Opaque,n formatter: fn(&Opaque, &mut Formatter<'_>) -> Result,n}nn// This guarantees a single stable value for the function pointer associated withn// indices/counts in the formatting infrastructure.n//n// Note that a function defined as such would not be correct as functions aren// always tagged unnamed_addr with the current lowering to LLVM IR, so theirn// address is not considered important to LLVM and as such the as_usize castn// could have been miscompiled. In practice, we never call as_usize on non-usizen// containing data (as a matter of static generation of the formattingn// arguments), so this is merely an additional check.n//n// We primarily want to ensure that the function pointer at `USIZE_MARKER` hasn// an address corresponding *only* to functions that also take `&usize` as theirn// first argument. The read_volatile here ensures that we can safely ready out an// usize from the passed reference and that this address does not point at an// non-usize taking function.n#[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]nstatic USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |ptr, _| {n // SAFETY: ptr is a referencen let _v: usize = unsafe { crate::ptr::read_volatile(ptr) };n loop {}n};nnimpl<'a> ArgumentV1<'a> {n #[doc(hidden)]n #[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]n pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> {n // SAFETY: `mem::transmute(x)` is safe becausen // 1. `&'b T` keeps the lifetime it originated with `'b`n // (so as to not have an unbounded lifetime)n // 2. `&'b T` and `&'b Opaque` have the same memory layoutn // (when `T` is `Sized`, as it is here)n // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`n // and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABIn // (as long as `T` is `Sized`)n unsafe { ArgumentV1 { formatter: mem::transmute(f), value: mem::transmute(x) } }n }nn #[doc(hidden)]n #[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]n pub fn from_usize(x: &usize) -> ArgumentV1<'_> {n ArgumentV1::new(x, USIZE_MARKER)n }nn fn as_usize(&self) -> Option<usize> {n if self.formatter as usize == USIZE_MARKER as usize {n // SAFETY: The `formatter` field is only set to USIZE_MARKER ifn // the value is a usize, so this is safen Some(unsafe { *(self.value as *const _ as *const usize) })n } else {n Nonen }n }n}nn// flags available in the v1 format of format_argsn#[derive(Copy, Clone)]nenum FlagV1 {n SignPlus,n SignMinus,n Alternate,n SignAwareZeroPad,n DebugLowerHex,n DebugUpperHex,n}nnimpl<'a> Arguments<'a> {n /// When using the format_args!() macro, this function is used to generate then /// Arguments structure.n #[doc(hidden)]n #[inline]n #[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]n pub fn new_v1(pieces: &'a [&'a str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {n Arguments { pieces, fmt: None, args }n }nn /// This function is used to specify nonstandard formatting parameters.n /// The `pieces` array must be at least as long as `fmt` to constructn /// a valid Arguments structure. Also, any `Count` within `fmt` that isn /// `CountIsParam` or `CountIsNextParam` has to point to an argumentn /// created with `argumentusize`. However, failing to do so doesn't causen /// unsafety, but will ignore invalid .n #[doc(hidden)]n #[inline]n #[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]n pub fn new_v1_formatted(n pieces: &'a [&'a str],n args: &'a [ArgumentV1<'a>],n fmt: &'a [rt::v1::Argument],n ) -> Arguments<'a> {n Arguments { pieces, fmt: Some(fmt), args }n }nn /// Estimates the length of the formatted text.n ///n /// This is intended to be used for setting initial `String` capacityn /// when using `format!`. Note: this is neither the lower nor upper bound.n #[doc(hidden)]n #[inline]n #[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]n pub fn estimated_capacity(&self) -> usize {n let pieces_length: usize = self.pieces.iter().map(|x| x.len()).sum();nn if self.args.is_empty() {n pieces_lengthn } else if self.pieces[0] == '' && pieces_length < 16 {n // If the format string starts with an argument,n // don't preallocate anything, unless lengthn // of pieces is significant.n 0n } else {n // There are some arguments, so any additional pushn // will reallocate the string. To avoid that,n // we're 'pre-doubling' the capacity here.n pieces_length.checked_mul(2).unwrap_or(0)n }n }n}nn/// This structure represents a safely precompiled version of a format stringn/// and its arguments. This cannot be generated at runtime because it cannotn/// safely be done, so no constructors are given and the fields are privaten/// to prevent modification.n///n/// The [`format_args!`] macro will safely create an instance of this structure.n/// The macro validates the format string at compile-time so usage of then/// [`write`] and [`format`] functions can be safely performed.n///n/// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug`n/// and `Display` contexts as seen below. The example also shows that `Debug`n/// and `Display` format to the same thing: the interpolated format stringn/// in `format_args!`.n///n/// ```rustn/// let debug = format!('{:?}', format_args!('{} foo {:?}', 1, 2));n/// let display = format!('{}', format_args!('{} foo {:?}', 1, 2));n/// assert_eq!('1 foo 2', display);n/// assert_eq!(display, debug);n/// ```n///n/// [`format_args!`]: ../../std/macro.format_args.htmln/// [`format`]: ../../std/fmt/fn.format.htmln/// [`write`]: ../../std/fmt/fn.write.htmln#[stable(feature = 'rust1', since = '1.0.0')]n#[derive(Copy, Clone)]npub struct Arguments<'a> {n // Format string pieces to print.n pieces: &'a [&'a str],nn // Placeholder specs, or `None` if all specs are default (as in '{}{}').n fmt: Option<'''// '''&'a [rt::v1::Ar'_start'gum'nod'ent'']>,nn // Dynami' let next = (*self.here_ptr()).get_next_ptr();n if next.is_null() { None }n else {n debug_assert!((*next).num_items > 0);n Some((*next).items[0].as_mut_ptr())n }n'c argum''''en'// 'ts for interpolation, to be interleaved with stringn // pieces. (Every argument is preceded by a string piece.)n args: &'a [ArgumentV1<'a>],n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Debug for Arguments<'_> {n fn fm'n 'pub(super) ''' pub(super) unsafe fn current_item<'a>(&self) -> Option<&'a Item> {n let node = &' self.p'_start'eek_next_node().map(|ptr| &*ptr)'' '// ''' '' '' '''''''_'v'e'r'p''' '' '' '' let next = ('// '*self.here_ptr()).get_n' '' 'n '// ' '''''''''local_inde''''''''''''''}' 'e'// ''n'o'''''''n '// ' 'debug_assert''''if self.local_index < node.num_items as usiz'// 'e'('!''''''g'u'b'e'd' '''' if self.local_index < n'// 'ode.num_items as usize'''''' 'e's'l'e''N' '{' '0' '='=' 'x'''// '''''l'a'c''// 'o'l'''''e'd'n'i'.'f'l'e's' 'f'i' ' 'ext_ptr();' 'n if ne''x' 't.is_null() { None ' '}' '' '''n else {' 'n ' ''' debug_assert!((*next).num_items > 0);' ' ' '' 'n '' '' Some((*next).items[0].as_mut_ptr())' 'n '' }' 'n'*self.here_ptr();''n if self.local_index < node.num_items as usize {n'' /''/ Ok - just return the current item.n Some(&*(node.items[self.local_index].as_ptr()))n } else {n // Peek the first item in the next node'nod'.n '' self.peek_next_item().map(|ptr| &*ptr)n '// ''' }n }n't(&'// 'self, fmt: &mut Forma'''''''''m'e't''''' 't'u''// 'm'i'_'''e'k'''''''''a't''// 'tter<'_>)'// ' -> Result'' {n Display:'// ':fmt(self, fmt)n '// '}n}nn#[stable(f''eature = 'rust1', sin'// 'ce = '1'// '.0.0')]nimpl Display'' for Arguments<'_> {n '// ' fn fmt(&'// 'self, fmt: &mut F'// 'ormatter''<'_>) -> Result {n '' '// ' write(fmt.'// 'buf, *'// 'self)n }n}nn///'// ' `?` f''ormatting.n///n/// `Debu'n '//'' ' 'u'// 'nimplement'// 'e''';')'('// ''d'''''''l'p'm'i'n'u''' 'g` should f''or'// 'mat the outpu'// 't in a pro'// 'grammer-facing, debugging context.n///n/// Generally speaking, you should just `derive` a `Debug` implementation.n///n/// When used with the alternate format specifier `#?`, the output is pretty-printed.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// This trait can be used with `#[derive]` if all fields implement `Debug`. Whenn/// `derive`d for structs, it will use the name of the `struct`, then `{`, then an/// comma-separated list of each field's name and `Debug` value, then `}`. Forn/// `enum`s, it will use the name of the variant and, if applicable, `(`, then then/// `Debug` values of the fields, then `)`.n///n/// # Stabilityn///n/// Derived `Debug` formats are not stable, and so may change with future Rustn/// versions. Additionally, `Debug` implementations of types provided by then/// standard library (`libstd`, `libcore`, `liballoc`, etc.) are not stable, andn/// may also change with future Rust versions.n///n/// # Examplesn///n/// Deriving an implementation:n///n/// ```n/// #[derive(Debug)]n/// struct Point {n/// x: i32,n/// y: i32,n/// }n///n/// let origin = Point { x: 0, y: 0 };n///n/// assert_eq!(format!('The origin is: {:?}', origin), 'The origin is: Point { x: 0, y: 0 }');n/// ```n///n/// Manually implementing:n///n/// ```n/// use std::fmt;n///n/// struct Point {n/// x: i32,n/// y: i32,n/// }n///n/// impl fmt::Debug for Point {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// f.debug_struct('Point')n/// .field('x', &self.x)n/// .field('y', &self.y)n/// .finish()n/// }n/// }n///n/// let origin = Point { x: 0, y: 0 };n///n/// assert_eq!(format!('The origin is: {:?}', origin), 'The origin is: Point { x: 0, y: 0 }');n/// ```n///n/// There are a number of helper methods on the [`Formatter`] struct to help you with manualn/// implementations, such as [`debug_struct`].n///n/// `Debug` implementations using either `derive` or the debug builder APIn/// on [`Formatter`] support pretty-printing using the alternate flag: `{:#?}`.n///n/// [`debug_struct`]: ../../std/fmt/struct.Formatter.html#method.debug_structn/// [`Formatter`]: ../../std/fmt/struct.Formatter.htmln///n/// Pretty-printing with `#?`:n///n/// ```n/// #[derive(Debug)]n/// struct Point {n/// x: i32,n/// y: i32,n/// }n///n/// let origin = Point { x: 0, y: 0 };n///n/// assert_eq!(format!('The origin is: {:#?}', origin),n/// 'The origin is: Point {n/// x: 0,n/// y: 0,n/// }');n/// ```nn#[stable(feature = 'rust1', since = '1.0.0')]n#[rustc_on_unimplemented(n on(n crate_local,n label = '`{Self}` cannot be formatted using `{{:?}}`',n note = 'add `#[derive(Debug)]` or manually implement `{Debug}`'n ),n message = '`{Self}` doesn't implement `{Debug}`',n label = '`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`'n)]n#[doc(alias = '{:?}')]n#[rustc_diagnostic_item = 'debug_trait']npub trait Debug {n /// Formats the value using the given formatter.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Position {n /// longitude: f32,n /// latitude: f32,n /// }n ///n /// impl fmt::Debug for Position {n /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n /// f.debug_tuple('')n /// .field(&self.longitude)n /// .field(&self.latitude)n /// .finish()n /// }n /// }n ///n /// let position = Position { longitude: 1.987, latitude: 2.983 };n /// assert_eq!(format!('{:?}', position), '(1.987, 2.983)');n ///n /// assert_eq!(format!('{:#?}', position), '(n /// 1.987,n /// 2.983,n /// )');n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn// Separate module to reexport the macro `Debug` from prelude without the trait `Debug`.npub(crate) mod macros {n /// Derive macro generating an impl of the trait `Debug`.n #[rustc_builtin_macro]n #[stable(feature = 'builtin_macro_prelude', since = '1.38.0')]n #[allow_internal_unstable(core_intrinsics)]n pub macro Debug($item:item) {n /* compiler built-in */n }n}n#[stable(feature = 'builtin_macro_prelude', since = '1.38.0')]n#[doc(inline)]npub use macros::Debug;nn/// Format trait for an empty format, `{}`.n///n/// `Display` is similar to [`Debug`][debug], but `Display` is for user-facingn/// output, and so cannot be derived.n///n/// [debug]: trait.Debug.htmln///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// # Examplesn///n/// Implementing `Display` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Point {n/// x: i32,n/// y: i32,n/// }n///n/// impl fmt::Display for Point {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// write!(f, '({}, {})', self.x, self.y)n/// }n/// }n///n/// let origin = Point { x: 0, y: 0 };n///n/// assert_eq!(format!('The origin is: {}', origin), 'The origin is: (0, 0)');n/// ```n#[rustc_on_unimplemented(n on(n _Self = 'std::path::Path',n label = '`{Self}` cannot be formatted with the default formatter; call `.display()` on it',n note = 'call `.display()` or `.to_string_lossy()` to safely print paths, n as they may contain non-Unicode data'n ),n message = '`{Self}` doesn't implement `{Display}`',n label = '`{Self}` cannot be formatted with the default formatter',n note = 'in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead'n)]n#[doc(alias = '{}')]n#[stable(feature = 'rust1', since = '1.0.0')]npub trait Display {n /// Formats the value using the given formatter.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Position {n /// longitude: f32,n /// latitude: f32,n /// }n ///n /// impl fmt::Display for Position {n /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n /// write!(f, '({}, {})', self.longitude, self.latitude)n /// }n /// }n ///n /// assert_eq!('(1.987, 2.983)',n /// format!('{}', Position { longitude: 1.987, latitude: 2.983, }));n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// `o` formatting.n///n/// The `Octal` trait should format its output as a number in base-8.n///n/// For primitive signed integers (`i8` to `i128`, and `isize`),n/// negative values are formatted as the two_s complement representation.n///n/// The alternate flag, `#`, adds a `0o` in front of the output.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// # Examplesn///n/// Basic usage with `i32`:n///n/// ```n/// let x = 42; // 42 is '52' in octaln///n/// assert_eq!(format!('{:o}', x), '52');n/// assert_eq!(format!('{:#o}', x), '0o52');n///n/// assert_eq!(format!('{:o}', -16), '37777777760');n/// ```n///n/// Implementing `Octal` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Length(i32);n///n/// impl fmt::Octal for Length {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// let val = self.0;n///n/// fmt::Octal::fmt(&val, f) // delegate to i32's implementationn/// }n/// }n///n/// let l = Length(9);n///n/// assert_eq!(format!('l as octal is: {:o}', l), 'l as octal is: 11');n///n/// assert_eq!(format!('l as octal is: {:#06o}', l), 'l as octal is: 0o0011');n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]npub trait Octal {n /// Formats the value using the given formatter.n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// `b` formatting.n///n/// The `Binary` trait should format its output as a number in binary.n///n/// For primitive signed integers ([`i8`] to [`i128`], and [`isize`]),n/// negative values are formatted as the two_s complement representation.n///n/// The alternate flag, `#`, adds a `0b` in front of the output.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// # Examplesn///n/// Basic usage with [`i32`]:n///n/// ```n/// let x = 42; // 42 is '101010' in binaryn///n/// assert_eq!(format!('{:b}', x), '101010');n/// assert_eq!(format!('{:#b}', x), '0b101010');n///n/// assert_eq!(format!('{:b}', -16), '11111111111111111111111111110000');n/// ```n///n/// Implementing `Binary` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Length(i32);n///n/// impl fmt::Binary for Length {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// let val = self.0;n///n/// fmt::Binary::fmt(&val, f) // delegate to i32's implementationn/// }n/// }n///n/// let l = Length(107);n///n/// assert_eq!(format!('l as binary is: {:b}', l), 'l as binary is: 1101011');n///n/// assert_eq!(n/// format!('l as binary is: {:#032b}', l),n/// 'l as binary is: 0b000000000000000000000001101011'n/// );n/// ```n///n/// [module]: ../../std/fmt/index.htmln/// [`i8`]: ../../std/primitive.i8.htmln/// [`i128`]: ../../std/primitive.i128.htmln/// [`isize`]: ../../std/primitive.isize.htmln/// [`i32`]: ../../std/primitive.i32.htmln#[stable(feature = 'rust1', since = '1.0.0')]npub trait Binary {n /// Formats the value using the given formatter.n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// `x` formatting.n///n/// The `LowerHex` trait should format its output as a number in hexadecimal, with `a` through `f`n/// in lower case.n///n/// For primitive signed integers (`i8` to `i128`, and `isize`),n/// negative values are formatted as the two_s complement representation.n///n/// The alternate flag, `#`, adds a `0x` in front of the output.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// # Examplesn///n/// Basic usage with `i32`:n///n/// ```n/// let x = 42; // 42 is '2a' in hexn///n/// assert_eq!(format!('{:x}', x), '2a');n/// assert_eq!(format!('{:#x}', x), '0x2a');n///n/// assert_eq!(format!('{:x}', -16), 'fffffff0');n/// ```n///n/// Implementing `LowerHex` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Length(i32);n///n/// impl fmt::LowerHex for Length {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// let val = self.0;n///n/// fmt::LowerHex::fmt(&val, f) // delegate to i32's implementationn/// }n/// }n///n/// let l = Length(9);n///n/// assert_eq!(format!('l as hex is: {:x}', l), 'l as hex is: 9');n///n/// assert_eq!(format!('l as hex is: {:#010x}', l), 'l as hex is: 0x00000009');n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]npub trait LowerHex {n /// Formats the value using the given formatter.n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// `X` formatting.n///n/// The `UpperHex` trait should format its output as a number in hexadecimal, with `A` through `F`n/// in upper case.n///n/// For primitive signed integers (`i8` to `i128`, and `isize`),n/// negative values are formatted as the two_s complement representation.n///n/// The alternate flag, `#`, adds a `0x` in front of the output.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// # Examplesn///n/// Basic usage with `i32`:n///n/// ```n/// let x = 42; // 42 is '2A' in hexn///n/// assert_eq!(format!('{:X}', x), '2A');n/// assert_eq!(format!('{:#X}', x), '0x2A');n///n/// assert_eq!(format!('{:X}', -16), 'FFFFFFF0');n/// ```n///n/// Implementing `UpperHex` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Length(i32);n///n/// impl fmt::UpperHex for Length {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// let val = self.0;n///n/// fmt::UpperHex::fmt(&val, f) // delegate to i32's implementationn/// }n/// }n///n/// let l = Length(i32::MAX);n///n/// assert_eq!(format!('l as hex is: {:X}', l), 'l as hex is: 7FFFFFFF');n///n/// assert_eq!(format!('l as hex is: {:#010X}', l), 'l as hex is: 0x7FFFFFFF');n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]npub trait UpperHex {n /// Formats the value using the given formatter.n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// `p` formatting.n///n/// The `Pointer` trait should format its output as a memory location. This is commonly presentedn/// as hexadecimal.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// # Examplesn///n/// Basic usage with `&i32`:n///n/// ```n/// let x = &42;n///n/// let address = format!('{:p}', x); // this produces something like '0x7f06092ac6d0'n/// ```n///n/// Implementing `Pointer` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Length(i32);n///n/// impl fmt::Pointer for Length {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// // use `as` to convert to a `*const T`, which implements Pointer, which we can usen///n/// let ptr = self as *const Self;n/// fmt::Pointer::fmt(&ptr, f)n/// }n/// }n///n/// let l = Length(42);n///n/// println!('l is in memory here: {:p}', l);n///n/// let l_ptr = format!('{:018p}', l);n/// assert_eq!(l_ptr.len(), 18);n/// assert_eq!(&l_ptr[..2], '0x');n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]npub trait Pointer {n /// Formats the value using the given formatter.n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// `e` formatting.n///n/// The `LowerExp` trait should format its output in scientific notation with a lower-case `e`.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// # Examplesn///n/// Basic usage with `f64`:n///n/// ```n/// let x = 42.0; // 42.0 is '4.2e1' in scientific notationn///n/// assert_eq!(format!('{:e}', x), '4.2e1');n/// ```n///n/// Implementing `LowerExp` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Length(i32);n///n/// impl fmt::LowerExp for Length {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// let val = f64::from(self.0);n/// fmt::LowerExp::fmt(&val, f) // delegate to f64's implementationn/// }n/// }n///n/// let l = Length(100);n///n/// assert_eq!(n/// format!('l in scientific notation is: {:e}', l),n/// 'l in scientific notation is: 1e2'n/// );n///n/// assert_eq!(n/// format!('l in scientific notation is: {:05e}', l),n/// 'l in scientific notation is: 001e2'n/// );n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]npub trait LowerExp {n /// Formats the value using the given formatter.n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// `E` formatting.n///n/// The `UpperExp` trait should format its output in scientific notation with an upper-case `E`.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// # Examplesn///n/// Basic usage with `f64`:n///n/// ```n/// let x = 42.0; // 42.0 is '4.2E1' in scientific notationn///n/// assert_eq!(format!('{:E}', x), '4.2E1');n/// ```n///n/// Implementing `UpperExp` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Length(i32);n///n/// impl fmt::UpperExp for Length {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// let val = f64::from(self.0);n/// fmt::UpperExp::fmt(&val, f) // delegate to f64's implementationn/// }n/// }n///n/// let l = Length(100);n///n/// assert_eq!(n/// format!('l in scientific notation is: {:E}', l),n/// 'l in scientific notation is: 1E2'n/// );n///n/// assert_eq!(n/// format!('l in scientific notation is: {:05E}', l),n/// 'l in scientific notation is: 001E2'n/// );n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]npub trait UpperExp {n /// Formats the value using the given formatter.n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// The `write` function takes an output stream, and an `Arguments` structn/// that can be precompiled with the `format_args!` macro.n///n/// The arguments will be formatted according to the specified format stringn/// into the output stream provided.n///n/// # Examplesn///n/// Basic usage:n///n/// ```n/// use std::fmt;n///n/// let mut output = String::new();n/// fmt::write(&mut output, format_args!('Hello {}!', 'world'))n/// .expect('Error occurred while trying to write in String');n/// assert_eq!(output, 'Hello world!');n/// ```n///n/// Please note that using [`write!`] might be preferable. Example:n///n/// ```n/// use std::fmt::Write;n///n/// let mut output = String::new();n/// write!(&mut output, 'Hello {}!', 'world')n/// .expect('Error occurred while trying to write in String');n/// assert_eq!(output, 'Hello world!');n/// ```n///n/// [`write!`]: ../../std/macro.write.htmln#[stable(feature = 'rust1', since = '1.0.0')]npub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {n let mut formatter = Formatter {n flags: 0,n width: None,n precision: None,n buf: output,n align: rt::v1::Alignment::Unknown,n fill: ' ',n };nn let mut idx = 0;nn match args.fmt {n None => {n // We can use default formatting parameters for all arguments.n for (arg, piece) in args.args.iter().zip(args.pieces.iter()) {n formatter.buf.write_str(*piece)?;n (arg.formatter)(arg.value, &mut formatter)?;n idx += 1;n }n }n Some(fmt) => {n // Every spec has a corresponding argument that is preceded byn // a string piece.n for (arg, piece) in fmt.iter().zip(args.pieces.iter()) {n formatter.buf.write_str(*piece)?;n run(&mut formatter, arg, &args.args)?;n idx += 1;n }n }n }nn // There can be only one trailing string piece left.n if let Some(piece) = args.pieces.get(idx) {n formatter.buf.write_str(*piece)?;n }nn Ok(())n}nnfn run(fmt: &mut Formatter<'_>, arg: &rt::v1::Argument, args: &[ArgumentV1<'_>]) -> Result {n fmt.fill = arg.format.fill;n fmt.align = arg.format.align;n fmt.flags = arg.format.flags;n fmt.width = getcount(args, &arg.format.width);n fmt.precision = getcount(args, &arg.format.precision);nn // Extract the correct argumentn let value = args[arg.position];nn // Then actually do some printingn (value.formatter)(value.value, fmt)n}nnfn getcount(args: &[ArgumentV1<'_>], cnt: &rt::v1::Count) -> Option<usize> {n match *cnt {n rt::v1::Count::Is(n) => Some(n),n rt::v1::Count::Implied => None,n rt::v1::Count::Param(i) => args[i].as_usize(),n }n}nn/// Padding after the end of something. Returned by `Formatter::padding`.n#[must_use = 'don't forget to write the post padding']nstruct PostPadding {n fill: char,n padding: usize,n}nnimpl PostPadding {n fn new(fill: char, padding: usize) -> PostPadding {n PostPadding { fill, padding }n }nn /// Write this post padding.n fn write(self, buf: &mut dyn Write) -> Result {n for _ in 0..self.padding {n buf.write_char(self.fill)?;n }n Ok(())n }n}nnimpl<'a> Formatter<'a> {n fn wrap_buf<'b, 'c, F>(&'b mut self, wrap: F) -> Formatter<'c>n wheren 'b: 'c,n F: FnOnce(&'b mut (dyn Write + 'b)) -> &'c mut (dyn Write + 'c),n {n Formatter {n // We want to change thisn buf: wrap(self.buf),nn // And preserve thesen flags: self.flags,n fill: self.fill,n align: self.align,n width: self.width,n precision: self.precision,n }n }nn // Helper methods used for padding and processing formatting arguments thatn // all formatting traits can use.nn /// Performs the correct padding for an integer which has already beenn /// emitted into a str. The str should *not* contain the sign for then /// integer, that will be added by this method.n ///n /// # Argumentsn ///n /// * is_nonnegative - whether the original integer was either positive or zero.n /// * prefix - if the '#' character (Alternate) is provided, thisn /// is the prefix to put in front of the number.n /// * buf - the byte array that the number has been formatted inton ///n /// This function will correctly account for the flags provided as well asn /// the minimum width. It will not take precision into account.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo { nb: i32 };n ///n /// impl Foo {n /// fn new(nb: i32) -> Foo {n /// Foo {n /// nb,n /// }n /// }n /// }n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// // We need to remove '-' from the number output.n /// let tmp = self.nb.abs().to_string();n ///n /// formatter.pad_integral(self.nb > 0, 'Foo ', &tmp)n /// }n /// }n ///n /// assert_eq!(&format!('{}', Foo::new(2)), '2');n /// assert_eq!(&format!('{}', Foo::new(-1)), '-1');n /// assert_eq!(&format!('{:#}', Foo::new(-1)), '-Foo 1');n /// assert_eq!(&format!('{:0>#8}', Foo::new(-1)), '00-Foo 1');n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n pub fn pad_integral(&mut self, is_nonnegative: bool, prefix: &str, buf: &str) -> Result {n let mut width = buf.len();nn let mut sign = None;n if !is_nonnegative {n sign = Some('-');n width += 1;n } else if self.sign_plus() {n sign = Some('+');n width += 1;n }nn let prefix = if self.alternate() {n width += prefix.chars().count();n Some(prefix)n } else {n Nonen };nn // Writes the sign if it exists, and then the prefix if it was requestedn #[inline(never)]n fn write_prefix(f: &mut Formatter<'_>, sign: Option<char>, prefix: Option<&str>) -> Result {n if let Some(c) = sign {n f.buf.write_char(c)?;n }n if let Some(prefix) = prefix { f.buf.write_str(prefix) } else { Ok(()) }n }nn // The `width` field is more of a `min-width` parameter at this point.n match self.width {n // If there's no minimum length requirements then we can justn // write the bytes.n None => {n write_prefix(self, sign, prefix)?;n self.buf.write_str(buf)n }n // Check if we're over the minimum width, if so then we can alson // just write the bytes.n Some(min) if width >= min => {n write_prefix(self, sign, prefix)?;n self.buf.write_str(buf)n }n // The sign and prefix goes before the padding if the fill charactern // is zeron Some(min) if self.sign_aware_zero_pad() => {n let old_fill = crate::mem::replace(&mut self.fill, '0');n let old_align = crate::mem::replace(&mut self.align, rt::v1::Alignment::Right);n write_prefix(self, sign, prefix)?;n let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?;n self.buf.write_str(buf)?;n post_padding.write(self.buf)?;n self.fill = old_fill;n self.align = old_align;n Ok(())n }n // Otherwise, the sign and prefix goes after the paddingn Some(min) => {n let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?;n write_prefix(self, sign, prefix)?;n self.buf.write_str(buf)?;n post_padding.write(self.buf)n }n }n }nn /// This function takes a string slice and emits it to the internal buffern /// after applying the relevant formatting flags specified. The flagsn /// recognized for generic strings are:n ///n /// * width - the minimum width of what to emitn /// * fill/align - what to emit and where to emit it if the stringn /// provided needs to be paddedn /// * precision - the maximum length to emit, the string is truncated if itn /// is longer than this lengthn ///n /// Notably this function ignores the `flag` parameters.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo;n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// formatter.pad('Foo')n /// }n /// }n ///n /// assert_eq!(&format!('{:<4}', Foo), 'Foo ');n /// assert_eq!(&format!('{:0>4}', Foo), '0Foo');n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n pub fn pad(&mut self, s: &str) -> Result {n // Make sure there's a fast path up frontn if self.width.is_none() && self.precision.is_none() {n return self.buf.write_str(s);n }n // The `precision` field can be interpreted as a `max-width` for then // string being formatted.n let s = if let Some(max) = self.precision {n // If our string is longer that the precision, then we must haven // truncation. However other flags like `fill`, `width` and `align`n // must act as always.n if let Some((i, _)) = s.char_indices().nth(max) {n // LLVM here can't prove that `..i` won't panic `&s[..i]`, butn // we know that it can't panic. Use `get` + `unwrap_or` to avoidn // `unsafe` and otherwise don't emit any panic-related coden // here.n s.get(..i).unwrap_or(&s)n } else {n &sn }n } else {n &sn };n // The `width` field is more of a `min-width` parameter at this point.n match self.width {n // If we're under the maximum length, and there's no minimum lengthn // requirements, then we can just emit the stringn None => self.buf.write_str(s),n // If we're under the maximum width, check if we're over the minimumn // width, if so it's as easy as just emitting the string.n Some(width) if s.chars().count() >= width => self.buf.write_str(s),n // If we're under both the maximum and the minimum width, then filln // up the minimum width with the specified string + some alignment.n Some(width) => {n let align = rt::v1::Alignment::Left;n let post_padding = self.padding(width - s.chars().count(), align)?;n self.buf.write_str(s)?;n post_padding.write(self.buf)n }n }n }nn /// Write the pre-padding and return the unwritten post-padding. Callers aren /// responsible for ensuring post-padding is written after the thing that isn /// being padded.n fn padding(n &mut self,n padding: usize,n default: rt::v1::Alignment,n ) -> result::Result<PostPadding, Error> {n let align = match self.align {n rt::v1::Alignment::Unknown => default,n _ => self.align,n };nn let (pre_pad, post_pad) = match align {n rt::v1::Alignment::Left => (0, padding),n rt::v1::Alignment::Right | rt::v1::Alignment::Unknown => (padding, 0),n rt::v1::Alignment::Center => (padding / 2, (padding + 1) / 2),n };nn for _ in 0..pre_pad {n self.buf.write_char(self.fill)?;n }nn Ok(PostPadding::new(self.fill, post_pad))n }nn /// Takes the formatted parts and applies the padding.n /// Assumes that the caller already has rendered the parts with required precision,n /// so that `self.precision` can be ignored.n fn pad_formatted_parts(&mut self, formatted: &flt2dec::Formatted<'_>) -> Result {n if let Some(mut width) = self.width {n // for the sign-aware zero padding, we render the sign first andn // behave as if we had no sign from the beginning.n let mut formatted = formatted.clone();n let old_fill = self.fill;n let old_align = self.align;n let mut align = old_align;n if self.sign_aware_zero_pad() {n // a sign always goes firstn let sign = formatted.sign;n self.buf.write_str(sign)?;nn // remove the sign from the formatted partsn formatted.sign = '';n width = width.saturating_sub(sign.len());n align = rt::v1::Alignment::Right;n self.fill = '0';n self.align = rt::v1::Alignment::Right;n }nn // remaining parts go through the ordinary padding process.n let len = formatted.len();n let ret = if width <= len {n // no paddingn self.write_formatted_parts(&formatted)n } else {n let post_padding = self.padding(width - len, align)?;n self.write_formatted_parts(&formatted)?;n post_padding.write(self.buf)n };n self.fill = old_fill;n self.align = old_align;n retn } else {n // this is the common case and we take a shortcutn self.write_formatted_parts(formatted)n }n }nn fn write_formatted_parts(&mut self, formatted: &flt2dec::Formatted<'_>) -> Result {n fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result {n // SAFETY: This is used for `flt2dec::Part::Num` and `flt2dec::Part::Copy`.n // It's safe to use for `flt2dec::Part::Num` since every char `c` is betweenn // `b'0'` and `b'9'`, which means `s` is valid UTF-8.n // It's also probably safe in practice to use for `flt2dec::Part::Copy(buf)`n // since `buf` should be plain ASCII, but it's possible for someone to passn // in a bad value for `buf` into `flt2dec::to_shortest_str` since it is an // public function.n // FIXME: Determine whether this could result in UB.n buf.write_str(unsafe { str::from_utf8_unchecked(s) })n }nn if !formatted.sign.is_empty() {n self.buf.write_str(formatted.sign)?;n }n for part in formatted.parts {n match *part {n flt2dec::Part::Zero(mut nzeroes) => {n const ZEROES: &str = // 64 zeroesn '0000000000000000000000000000000000000000000000000000000000000000';n while nzeroes > ZEROES.len() {n self.buf.write_str(ZEROES)?;n nzeroes -= ZEROES.len();n }n if nzeroes > 0 {n self.buf.write_str(&ZEROES[..nzeroes])?;n }n }n flt2dec::Part::Num(mut v) => {n let mut s = [0; 5];n let len = part.len();n for c in s[..len].iter_mut().rev() {n *c = b'0' + (v % 10) as u8;n v /= 10;n }n write_bytes(self.buf, &s[..len])?;n }n flt2dec::Part::Copy(buf) => {n write_bytes(self.buf, buf)?;n }n }n }n Ok(())n }nn /// Writes some data to the underlying buffer contained within thisn /// formatter.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo;n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// formatter.write_str('Foo')n /// // This is equivalent to:n /// // write!(formatter, 'Foo')n /// }n /// }n ///n /// assert_eq!(&format!('{}', Foo), 'Foo');n /// assert_eq!(&format!('{:0>8}', Foo), 'Foo');n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n pub fn write_str(&mut self, data: &str) -> Result {n self.buf.write_str(data)n }nn /// Writes some formatted information into this instance.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo(i32);n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// formatter.write_fmt(format_args!('Foo {}', self.0))n /// }n /// }n ///n /// assert_eq!(&format!('{}', Foo(-1)), 'Foo -1');n /// assert_eq!(&format!('{:0>8}', Foo(2)), 'Foo 2');n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n pub fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result {n write(self.buf, fmt)n }nn /// Flags for formattingn #[stable(feature = 'rust1', since = '1.0.0')]n #[rustc_deprecated(n since = '1.24.0',n reason = 'use the `sign_plus`, `sign_minus`, `alternate`, n or `sign_aware_zero_pad` methods instead'n )]n pub fn flags(&self) -> u32 {n self.flagsn }nn /// Character used as 'fill' whenever there is alignment.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo;n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// let c = formatter.fill();n /// if let Some(width) = formatter.width() {n /// for _ in 0..width {n /// write!(formatter, '{}', c)?;n /// }n /// Ok(())n /// } else {n /// write!(formatter, '{}', c)n /// }n /// }n /// }n ///n /// // We set alignment to the left with '>'.n /// assert_eq!(&format!('{:G>3}', Foo), 'GGG');n /// assert_eq!(&format!('{:t>6}', Foo), 'tttttt');n /// ```n #[stable(feature = 'fmt_flags', since = '1.5.0')]n pub fn fill(&self) -> char {n self.filln }nn /// Flag indicating what form of alignment was requested.n ///n /// # Examplesn ///n /// ```n /// extern crate core;n ///n /// use std::fmt::{self, Alignment};n ///n /// struct Foo;n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// let s = if let Some(s) = formatter.align() {n /// match s {n /// Alignment::Left => 'left',n /// Alignment::Right => 'right',n /// Alignment::Center => 'center',n /// }n /// } else {n /// 'into the void'n /// };n /// write!(formatter, '{}', s)n /// }n /// }n ///n /// assert_eq!(&format!('{:<}', Foo), 'left');n /// assert_eq!(&format!('{:>}', Foo), 'right');n /// assert_eq!(&format!('{:^}', Foo), 'center');n /// assert_eq!(&format!('{}', Foo), 'into the void');n /// ```n #[stable(feature = 'fmt_flags_align', since = '1.28.0')]n pub fn align(&self) -> Option<Alignment> {n match self.align {n rt::v1::Alignment::Left => Some(Alignment::Left),n rt::v1::Alignment::Right => Some(Alignment::Right),n rt::v1::Alignment::Center => Some(Alignment::Center),n rt::v1::Alignment::Unknown => None,n }n }nn /// Optionally specified integer width that the output should be.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo(i32);n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// if let Some(width) = formatter.width() {n /// // If we received a width, we use itn /// write!(formatter, '{:width$}', &format!('Foo({})', self.0), width = width)n /// } else {n /// // Otherwise we do nothing specialn /// write!(formatter, 'Foo({})', self.0)n /// }n /// }n /// }n ///n /// assert_eq!(&format!('{:10}', Foo(23)), 'Foo(23) ');n /// assert_eq!(&format!('{}', Foo(23)), 'Foo(23)');n /// ```n #[stable(feature = 'fmt_flags', since = '1.5.0')]n pub fn width(&self) -> Option<usize> {n self.widthn }nn /// Optionally specified precision for numeric types. Alternatively, then /// maximum width for string types.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo(f32);n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// if let Some(precision) = formatter.precision() {n /// // If we received a precision, we use it.n /// write!(formatter, 'Foo({1:.*})', precision, self.0)n /// } else {n /// // Otherwise we default to 2.n /// write!(formatter, 'Foo({:.2})', self.0)n /// }n /// }n /// }n ///n /// assert_eq!(&format!('{:.4}', Foo(23.2)), 'Foo(23.2000)');n /// assert_eq!(&format!('{}', Foo(23.2)), 'Foo(23.20)');n /// ```n #[stable(feature = 'fmt_flags', since = '1.5.0')]n pub fn precision(&self) -> Option<usize> {n self.precisionn }nn /// Determines if the `+` flag was specified.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo(i32);n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// if formatter.sign_plus() {n /// write!(formatter,n /// 'Foo({}{})',n /// if self.0 < 0 { '-' } else { '+' },n /// self.0)n /// } else {n /// write!(formatter, 'Foo({})', self.0)n /// }n /// }n /// }n ///n /// assert_eq!(&format!('{:+}', Foo(23)), 'Foo(+23)');n /// assert_eq!(&format!('{}', Foo(23)), 'Foo(23)');n /// ```n #[stable(feature = 'fmt_flags', since = '1.5.0')]n pub fn sign_plus(&self) -> bool {n self.flags & (1 << FlagV1::SignPlus as u32) != 0n }nn /// Determines if the `-` flag was specified.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo(i32);n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// if formatter.sign_minus() {n /// // You want a minus sign? Have one!n /// write!(formatter, '-Foo({})', self.0)n /// } else {n /// write!(formatter, 'Foo({})', self.0)n /// }n /// }n /// }n ///n /// assert_eq!(&format!('{:-}', Foo(23)), '-Foo(23)');n /// assert_eq!(&format!('{}', Foo(23)), 'Foo(23)');n /// ```n #[stable(feature = 'fmt_flags', since = '1.5.0')]n pub fn sign_minus(&self) -> bool {n self.flags & (1 << FlagV1::SignMinus as u32) != 0n }nn /// Determines if the `#` flag was specified.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo(i32);n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// if formatter.alternate() {n /// write!(formatter, 'Foo({})', self.0)n /// } else {n /// write!(formatter, '{}', self.0)n /// }n /// }n /// }n ///n /// assert_eq!(&format!('{:#}', Foo(23)), 'Foo(23)');n /// assert_eq!(&format!('{}', Foo(23)), '23');n /// ```n #[stable(feature = 'fmt_flags', since = '1.5.0')]n pub fn alternate(&self) -> bool {n self.flags & (1 << FlagV1::Alternate as u32) != 0n }nn /// Determines if the `0` flag was specified.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo(i32);n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// assert!(formatter.sign_aware_zero_pad());n /// assert_eq!(formatter.width(), Some(4));n /// // We ignore the formatter's options.n /// write!(formatter, '{}', self.0)n /// }n /// }n ///n /// assert_eq!(&format!('{:04}', Foo(23)), '23');n /// ```n #[stable(feature = 'fmt_flags', since = '1.5.0')]n pub fn sign_aware_zero_pad(&self) -> bool {n self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0n }nn // FIXME: Decide what public API we want for these two flags.n // https://github.com/rust-lang/rust/issues/48584n fn debug_lower_hex(&self) -> bool {n self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0n }nn fn debug_upper_hex(&self) -> bool {n self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0n }nn /// Creates a [`DebugStruct`] builder designed to assist with creation ofn /// [`fmt::Debug`] implementations for structs.n ///n /// [`DebugStruct`]: ../../std/fmt/struct.DebugStruct.htmln /// [`fmt::Debug`]: ../../std/fmt/trait.Debug.htmln ///n /// # Examplesn ///n /// ```rustn /// use std::fmt;n /// use std::net::Ipv4Addr;n ///n /// struct Foo {n /// bar: i32,n /// baz: String,n /// addr: Ipv4Addr,n /// }n ///n /// impl fmt::Debug for Foo {n /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {n /// fmt.debug_struct('Foo')n /// .field('bar', &self.bar)n /// .field('baz', &self.baz)n /// .field('addr', &format_args!('{}', self.addr))n /// .finish()n /// }n /// }n ///n /// assert_eq!(n /// 'Foo { bar: 10, baz: 'Hello World', addr: 127.0.0.1 }',n /// format!('{:?}', Foo {n /// bar: 10,n /// baz: 'Hello World'.to_string(),n /// addr: Ipv4Addr::new(127, 0, 0, 1),n /// })n /// );n /// ```n #[stable(feature = 'debug_builders', since = '1.2.0')]n pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> {n builders::debug_struct_new(self, name)n }nn /// Creates a `DebugTuple` builder designed to assist with creation ofn /// `fmt::Debug` implementations for tuple structs.n ///n /// # Examplesn ///n /// ```rustn /// use std::fmt;n /// use std::marker::PhantomData;n ///n /// struct Foo<T>(i32, String, PhantomData<T>);n ///n /// impl<T> fmt::Debug for Foo<T> {n /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {n /// fmt.debug_tuple('Foo')n /// .field(&self.0)n /// .field(&self.1)n /// .field(&format_args!('_'))n /// .finish()n /// }n /// }n ///n /// assert_eq!(n /// 'Foo(10, 'Hello', _)',n /// format!('{:?}', Foo(10, 'Hello'.to_string(), PhantomData::<u8>))n /// );n /// ```n #[stable(feature = 'debug_builders', since = '1.2.0')]n pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> {n builders::debug_tuple_new(self, name)n }nn /// Creates a `DebugList` builder designed to assist with creation ofn /// `fmt::Debug` implementations for list-like structures.n ///n /// # Examplesn ///n /// ```rustn /// use std::fmt;n ///n /// struct Foo(Vec<i32>);n ///n /// impl fmt::Debug for Foo {n /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {n /// fmt.debug_list().entries(self.0.iter()).finish()n /// }n /// }n ///n /// assert_eq!(format!('{:?}', Foo(vec![10, 11])), '[10, 11]');n /// ```n #[stable(feature = 'debug_builders', since = '1.2.0')]n pub fn debug_list<'b>(&'b mut self) -> DebugList<'b, 'a> {n builders::debug_list_new(self)n }nn /// Creates a `DebugSet` builder designed to assist with creation ofn /// `fmt::Debug` implementations for set-like structures.n ///n /// # Examplesn ///n /// ```rustn /// use std::fmt;n ///n /// struct Foo(Vec<i32>);n ///n /// impl fmt::Debug for Foo {n /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {n /// fmt.debug_set().entries(self.0.iter()).finish()n /// }n /// }n ///n /// assert_eq!(format!('{:?}', Foo(vec![10, 11])), '{10, 11}');n /// ```n ///n /// [`format_args!`]: ../../std/macro.format_args.htmln ///n /// In this more complex example, we use [`format_args!`] and `.debug_set()`n /// to build a list of match arms:n ///n /// ```rustn /// use std::fmt;n ///n /// struct Arm<'a, L: 'a, R: 'a>(&'a (L, R));n /// struct Table<'a, K: 'a, V: 'a>(&'a [(K, V)], V);n ///n /// impl<'a, L, R> fmt::Debug for Arm<'a, L, R>n /// wheren /// L: 'a + fmt::Debug, R: 'a + fmt::Debugn /// {n /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {n /// L::fmt(&(self.0).0, fmt)?;n /// fmt.write_str(' => ')?;n /// R::fmt(&(self.0).1, fmt)n /// }n /// }n ///n /// impl<'a, K, V> fmt::Debug for Table<'a, K, V>n /// wheren /// K: 'a + fmt::Debug, V: 'a + fmt::Debugn /// {n /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {n /// fmt.debug_set()n /// .entries(self.0.iter().map(Arm))n /// .entry(&Arm(&(format_args!('_'), &self.1)))n /// .finish()n /// }n /// }n /// ```n #[stable(feature = 'debug_builders', since = '1.2.0')]n pub fn debug_set<'b>(&'b mut self) -> DebugSet<'b, 'a> {n builders::debug_set_new(self)n }nn /// Creates a `DebugMap` builder designed to assist with creation ofn /// `fmt::Debug` implementations for map-like structures.n ///n /// # Examplesn ///n /// ```rustn /// use std::fmt;n ///n /// struct Foo(Vec<(String, i32)>);n ///n /// impl fmt::Debug for Foo {n /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {n /// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish()n /// }n /// }n ///n /// assert_eq!(n /// format!('{:?}', Foo(vec![('A'.to_string(), 10), ('B'.to_string(), 11)])),n /// r#'{'A': 10, 'B': 11}'#n /// );n /// ```n #[stable(feature = 'debug_builders', since = '1.2.0')]n pub fn debug_map<'b>(&'b mut self) -> DebugMap<'b, 'a> {n builders::debug_map_new(self)n }n}nn#[stable(since = '1.2.0', feature = 'formatter_write')]nimpl Write for Formatter<'_> {n fn write_str(&mut self, s: &str) -> Result {n self.buf.write_str(s)n }nn fn write_char(&mut self, c: char) -> Result {n self.buf.write_char(c)n }nn fn write_fmt(&mut self, args: Arguments<'_>) -> Result {n write(self.buf, args)n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Display for Error {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Display::fmt('an error occurred when formatting an argument', f)n }n}nn// Implementations of the core formatting traitsnnmacro_rules! fmt_refs {n ($($tr:ident),*) => {n $(n #[stable(feature = 'rust1', since = '1.0.0')]n impl<T: ?Sized + $tr> $tr for &T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) }n }n #[stable(feature = 'rust1', since = '1.0.0')]n impl<T: ?Sized + $tr> $tr for &mut T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) }n }n )*n }n}nnfmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp }nn#[unstable(feature = 'never_type', issue = '35121')]nimpl Debug for ! {n fn fmt(&self, _: &mut Formatter<'_>) -> Result {n *selfn }n}nn#[unstable(feature = 'never_type', issue = '35121')]nimpl Display for ! {n fn fmt(&self, _: &mut Formatter<'_>) -> Result {n *selfn }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Debug for bool {n #[inline]n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Display::fmt(self, f)n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Display for bool {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Display::fmt(if *self { 'true' } else { 'false' }, f)n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Debug for str {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n f.write_char(''')?;n let mut from = 0;n for (i, c) in self.char_indices() {n let esc = c.escape_debug();n // If char needs escaping, flush backlog so far and write, else skipn if esc.len() != 1 {n f.write_str(&self[from..i])?;n for c in esc {n f.write_char(c)?;n }n from = i + c.len_utf8();n }n }n f.write_str(&self[from..])?;n f.write_char(''')n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Display for str {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n f.pad(self)n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Debug for char {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n f.write_char(''')?;n for c in self.escape_debug() {n f.write_char(c)?n }n f.write_char(''')n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Display for char {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n if f.width.is_none() && f.precision.is_none() {n f.write_char(*self)n } else {n f.pad(self.encode_utf8(&mut [0; 4]))n }n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: ?Sized> Pointer for *const T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n let old_width = f.width;n let old_flags = f.flags;nn // The alternate flag is already treated by LowerHex as being special-n // it denotes whether to prefix with 0x. We use it to work out whethern // or not to zero extend, and then unconditionally set it to get then // prefix.n if f.alternate() {n f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);nn if f.width.is_none() {n f.width = Some(((mem::size_of::<usize>() * 8) / 4) + 2);n }n }n f.flags |= 1 << (FlagV1::Alternate as u32);nn let ret = LowerHex::fmt(&(*self as *const () as usize), f);nn f.width = old_width;n f.flags = old_flags;nn retn }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: ?Sized> Pointer for *mut T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Pointer::fmt(&(*self as *const T), f)n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: ?Sized> Pointer for &T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Pointer::fmt(&(*self as *const T), f)n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: ?Sized> Pointer for &mut T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Pointer::fmt(&(&**self as *const T), f)n }n}nn// Implementation of Display/Debug for various core typesnn#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: ?Sized> Debug for *const T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Pointer::fmt(self, f)n }n}n#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: ?Sized> Debug for *mut T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Pointer::fmt(self, f)n }n}nnmacro_rules! peel {n ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* })n}nnmacro_rules! tuple {n () => ();n ( $($name:ident,)+ ) => (n #[stable(feature = 'rust1', since = '1.0.0')]n impl<$($name:Debug),+> Debug for ($($name,)+) where last_type!($($name,)+): ?Sized {n #[allow(non_snake_case, unused_assignments)]n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n let mut builder = f.debug_tuple('');n let ($(ref $name,)+) = *self;n $(n builder.field(&$name);n )+nn builder.finish()n }n }n peel! { $($name,)+ }n )n}nnmacro_rules! last_type {n ($a:ident,) => { $a };n ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) };n}nntuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: Debug> Debug for [T] {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n f.debug_list().entries(self.iter()).finish()n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Debug for () {n #[inline]n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n f.pad('()')n }n}n#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: ?Sized> Debug for PhantomData<T> {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n f.pad('PhantomData')n }n}''''//! Utilities for formatting and printing strings.nn#![stable(feature = 'rust1', since = '1.0.0')]nnuse crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};nuse crate::marker::PhantomData;nuse crate::mem;nuse crate::num::flt2dec;nuse crate::ops::Deref;nuse crate::result;nuse crate::str;nnmod builders;nmod float;nmod num;nn#[stable(feature = 'fmt_flags_align', since = '1.28.0')]n/// Possible alignments returned by `Formatter::align`n#[derive(Debug)]npub enum Alignment {n #[stable(feature = 'fmt_flags_align', since = '1.28.0')]n /// Indication that contents should be left-aligned.n Left,n #[stable(feature = 'fmt_flags_align', since = '1.28.0')]n /// Indication that contents should be right-aligned.n Right,n #[stable(feature = 'fmt_flags_align', since = '1.28.0')]n /// Indication that contents should be center-aligned.n Center,n}nn#[stable(feature = 'debug_builders', since = '1.2.0')]npub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};nn#[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]n#[doc(hidden)]npub mod rt {n pub mod v1;n}nn/// The type returned by formatter methods.n///n/// # Examplesn///n/// ```n/// use std::fmt;n///n/// #[derive(Debug)]n/// struct Triangle {n/// a: f32,n/// b: f32,n/// c: f32n/// }n///n/// impl fmt::Display for Triangle {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// write!(f, '({}, {}, {})', self.a, self.b, self.c)n/// }n/// }n///n/// let pythagorean_triple = Triangle { a: 3.0, b: 4.0, c: 5.0 };n///n/// assert_eq!(format!('{}', pythagorean_triple), '(3, 4, 5)');n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]npub type Result = result::Result<(), Error>;nn/// The error type which is returned from formatting a message into a stream.n///n/// This type does not support transmission of an error other than that an errorn/// occurred. Any extra information must be arranged to be transmitted throughn/// some other means.n///n/// An important thing to remember is that the type `fmt::Error` should not ben/// confused with [`std::io::Error`] or [`std::error::Error`], which you may alson/// have in scope.n///n/// [`std::io::Error`]: ../../std/io/struct.Error.htmln/// [`std::error::Error`]: ../../std/error/trait.Error.htmln///n/// # Examplesn///n/// ```rustn/// use std::fmt::{self, write};n///n/// let mut output = String::new();n/// if let Err(fmt::Error) = write(&mut output, format_args!('Hello {}!', 'world')) {n/// panic!('An error occurred');n/// }n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]n#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]npub struct Error;nn/// A collection of methods that are required to format a message into a stream.n///n/// This trait is the type which this modules requires when formattingn/// information. This is similar to the standard library's [`io::Write`] trait,n/// but it is only intended for use in libcore.n///n/// This trait should generally not be implemented by consumers of the standardn/// library. The [`write!`] macro accepts an instance of [`io::Write`], and then/// [`io::Write`] trait is favored over implementing this trait.n///n/// [`write!`]: ../../std/macro.write.htmln/// [`io::Write`]: ../../std/io/trait.Write.htmln#[stable(feature = 'rust1', since = '1.0.0')]npub trait Write {n /// Writes a string slice into this writer, returning whether the writen /// succeeded.n ///n /// This method can only succeed if the entire string slice was successfullyn /// written, and this method will not return until all data has beenn /// written or an error occurs.n ///n /// # Errorsn ///n /// This function will return an instance of [`Error`] on error.n ///n /// [`Error`]: struct.Error.htmln ///n /// # Examplesn ///n /// ```n /// use std::fmt::{Error, Write};n ///n /// fn writer<W: Write>(f: &mut W, s: &str) -> Result<(), Error> {n /// f.write_str(s)n /// }n ///n /// let mut buf = String::new();n /// writer(&mut buf, 'hola').unwrap();n /// assert_eq!(&buf, 'hola');n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n fn write_str(&mut self, s: &str) -> Result;nn /// Writes a [`char`] into this writer, returning whether the write succeeded.n ///n /// A single [`char`] may be encoded as more than one byte.n /// This method can only succeed if the entire byte sequence was successfullyn /// written, and this method will not return until all data has beenn /// written or an error occurs.n ///n /// # Errorsn ///n /// This function will return an instance of [`Error`] on error.n ///n /// [`char`]: ../../std/primitive.char.htmln /// [`Error`]: struct.Error.htmln ///n /// # Examplesn ///n /// ```n /// use std::fmt::{Error, Write};n ///n /// fn writer<W: Write>(f: &mut W, c: char) -> Result<(), Error> {n /// f.write_char(c)n /// }n ///n /// let mut buf = String::new();n /// writer(&mut buf, 'a').unwrap();n /// writer(&mut buf, 'b').unwrap();n /// assert_eq!(&buf, 'ab');n /// ```n #[stable(feature = 'fmt_write_char', since = '1.1.0')]n fn write_char(&mut self, c: char) -> Result {n self.write_str(c.encode_utf8(&mut [0; 4]))n }nn /// Glue for usage of the [`write!`] macro with implementors of this trait.n ///n /// This method should generally not be invoked manually, but rather throughn /// the [`write!`] macro itself.n ///n /// [`write!`]: ../../std/macro.write.htmln ///n /// # Examplesn ///n /// ```n /// use std::fmt::{Error, Write};n ///n /// fn writer<W: Write>(f: &mut W, s: &str) -> Result<(), Error> {n /// f.write_fmt(format_args!('{}', s))n /// }n ///n /// let mut buf = String::new();n /// writer(&mut buf, 'world').unwrap();n /// assert_eq!(&buf, 'world');n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n fn write_fmt(mut self: &mut Self, args: Arguments<'_>) -> Result {n write(&mut self, args)n }n}nn#[stable(feature = 'fmt_write_blanket_impl', since = '1.4.0')]nimpl<W: Write + ?Sized> Write for &mut W {n fn write_str(&mut self, s: &str) -> Result {n (**self).write_str(s)n }nn fn write_char(&mut self, c: char) -> Result {n (**self).write_char(c)n }nn fn write_fmt(&mut self, args: Arguments<'_>) -> Result {n (**self).write_fmt(args)n }n}nn/// Configuration for formatting.n///n/// A `Formatter` represents various options related to formatting. Users do notn/// construct `Formatter`s directly; a mutable reference to one is passed ton/// the `fmt` method of all formatting traits, like [`Debug`] and [`Display`].n///n/// To interact with a `Formatter`, you'll call various methods to change then/// various options related to formatting. For examples, please see then/// documentation of the methods defined on `Formatter` below.n///n/// [`Debug`]: trait.Debug.htmln/// [`Display`]: trait.Display.htmln#[allow(missing_debug_implementations)]n#[stable(feature = 'rust1', since = '1.0.0')]npub struct Formatter<'a> {n flags: u32,n fill: char,n align: rt::v1::Alignment,n width: Option<usize>,n precision: Option<usize>,nn buf: &'a mut (dyn Write + 'a),n}nn// NB. Argument is essentially an optimized partially applied formatting function,n// equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`.nnextern 'C' {n type Opaque;n}nn/// This struct represents the generic 'argument' which is taken by the Xprintfn/// family of functions. It contains a function to format the given value. Atn/// compile time it is ensured that the function and the value have the correctn/// types, and then this struct is used to canonicalize arguments to one type.n#[derive(Copy, Clone)]n#[allow(missing_debug_implementations)]n#[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]n#[doc(hidden)]npub struct ArgumentV1<'a> {n value: &'a Opaque,n formatter: fn(&Opaque, &mut Formatter<'_>) -> Result,n}nn// This guarantees a single stable value for the function pointer associated withn// indices/counts in the formatting infrastructure.n//n// Note that a function defined as such would not be correct as functions aren// always tagged unnamed_addr with the current lowering to LLVM IR, so theirn// address is not considered important to LLVM and as such the as_usize castn// could have been miscompiled. In practice, we never call as_usize on non-usizen// containing data (as a matter of static generation of the formattingn// arguments), so this is merely an additional check.n//n// We primarily want to ensure that the function pointer at `USIZE_MARKER` hasn// an address corresponding *only* to functions that also take `&usize` as theirn// first argument. The read_volatile here ensures that we can safely ready out an// usize from the passed reference and that this address does not point at an// non-usize taking function.n#[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]nstatic USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |ptr, _| {n // SAFETY: ptr is a referencen let _v: usize = unsafe { crate::ptr::read_volatile(ptr) };n loop {}n};nnimpl<'a> ArgumentV1<'a> {n #[doc(hidden)]n #[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]n pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> {n // SAFETY: `mem::transmute(x)` is safe becausen // 1. `&'b T` keeps the lifetime it originated with `'b`n // (so as to not have an unbounded lifetime)n // 2. `&'b T` and `&'b Opaque` have the same memory layoutn // (when `T` is `Sized`, as it is here)n // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result`n // and `fn(&Opaque, &mut Formatter<'_>) -> Result` have the same ABIn // (as long as `T` is `Sized`)n unsafe { ArgumentV1 { formatter: mem::transmute(f), value: mem::transmute(x) } }n }nn #[doc(hidden)]n #[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]n pub fn from_usize(x: &usize) -> ArgumentV1<'_> {n ArgumentV1::new(x, USIZE_MARKER)n }nn fn as_usize(&self) -> Option<usize> {n if self.formatter as usize == USIZE_MARKER as usize {n // SAFETY: The `formatter` field is only set to USIZE_MARKER ifn // the value is a usize, so this is safen Some(unsafe { *(self.value as *const _ as *const usize) })n } else {n Nonen }n }n}nn// flags available in the v1 format of format_argsn#[derive(Copy, Clone)]nenum FlagV1 {n SignPlus,n SignMinus,n Alternate,n SignAwareZeroPad,n DebugLowerHex,n DebugUpperHex,n}nnimpl<'a> Arguments<'a> {n /// When using the format_args!() macro, this function is used to generate then /// Arguments structure.n #[doc(hidden)]n #[inline]n #[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]n pub fn new_v1(pieces: &'a [&'a str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {n Arguments { pieces, fmt: None, args }n }nn /// This function is used to specify nonstandard formatting parameters.n /// The `pieces` array must be at least as long as `fmt` to constructn /// a valid Arguments structure. Also, any `Count` within `fmt` that isn /// `CountIsParam` or `CountIsNextParam` has to point to an argumentn /// created with `argumentusize`. However, failing to do so doesn't causen /// unsafety, but will ignore invalid .n #[doc(hidden)]n #[inline]n #[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]n pub fn new_v1_formatted(n pieces: &'a [&'a str],n args: &'a [ArgumentV1<'a>],n fmt: &'a [rt::v1::Argument],n ) -> Arguments<'a> {n Arguments { pieces, fmt: Some(fmt), args }n }nn /// Estimates the length of the formatted text.n ///n /// This is intended to be used for setting initial `String` capacityn /// when using `format!`. Note: this is neither the lower nor upper bound.n #[doc(hidden)]n #[inline]n #[unstable(feature = 'fmt_internals', reason = 'internal to format_args!', issue = 'none')]n pub fn estimated_capacity(&self) -> usize {n let pieces_length: usize = self.pieces.iter().map(|x| x.len()).sum();nn if self.args.is_empty() {n pieces_lengthn } else if self.pieces[0] == '' && pieces_length < 16 {n // If the format string starts with an argument,n // don't preallocate anything, unless lengthn // of pieces is significant.n 0n } else {n // There are some arguments, so any additional pushn // will reallocate the string. To avoid that,n // we're 'pre-doubling' the capacity here.n pieces_length.checked_mul(2).unwrap_or(0)n }n }n}nn/// This structure represents a safely precompiled version of a format stringn/// and its arguments. This cannot be generated at runtime because it cannotn/// safely be done, so no constructors are given and the fields are privaten/// to prevent modification.n///n/// The [`format_args!`] macro will safely create an instance of this structure.n/// The macro validates the format string at compile-time so usage of then/// [`write`] and [`format`] functions can be safely performed.n///n/// You can use the `Arguments<'a>` that [`format_args!`] returns in `Debug`n/// and `Display` contexts as seen below. The example also shows that `Debug`n/// and `Display` format to the same thing: the interpolated format stringn/// in `format_args!`.n///n/// ```rustn/// let debug = format!('{:?}', format_args!('{} foo {:?}', 1, 2));n/// let display = format!('{}', format_args!('{} foo {:?}', 1, 2));n/// assert_eq!('1 foo 2', display);n/// assert_eq!(display, debug);n/// ```n///n/// [`format_args!`]: ../../std/macro.format_args.htmln/// [`format`]: ../../std/fmt/fn.format.htmln/// [`write`]: ../../std/fmt/fn.write.htmln#[stable(feature = 'rust1', since = '1.0.0')]n#[derive(Copy, Clone)]npub struct Arguments<'a> {n // Format string pieces to print.n pieces: &'a [&'a str],nn // Placeholder specs, or `None` if all specs are default (as in '{}{}').n fmt: Option<&'a [rt::v1::Argument]>,nn // Dynamic arguments for interpolation, to be interleaved with stringn // pieces. (Every argument is preceded by a string piece.)n args: &'a [ArgumentV1<'a>],n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Debug for Arguments<'_> {n fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {n Display::fmt(self, fmt)n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Display for Arguments<'_> {n fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {n write(fmt.buf, *self)n }n}nn/// `?` formatting.n///n/// `Debug` should format the output in a programmer-facing, debugging context.n///n/// Generally speaking, you should just `derive` a `Debug` implementation.n///n/// When used with the alternate format specifier `#?`, the output is pretty-printed.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// This trait can be used with `#[derive]` if all fields implement `Debug`. Whenn/// `derive`d for structs, it will use the name of the `struct`, then `{`, then an/// comma-separated list of each field's name and `Debug` value, then `}`. Forn/// `enum`s, it will use the name of the variant and, if applicable, `(`, then then/// `Debug` values of the fields, then `)`.n///n/// # Stabilityn///n/// Derived `Debug` formats are not stable, and so may change with future Rustn/// versions. Additionally, `Debug` implementations of types provided by then/// standard library (`libstd`, `libcore`, `liballoc`, etc.) are not stable, andn/// may also change with future Rust versions.n///n/// # Examplesn///n/// Deriving an implementation:n///n/// ```n/// #[derive(Debug)]n/// struct Point {n/// x: i32,n/// y: i32,n/// }n///n/// let origin = Point { x: 0, y: 0 };n///n/// assert_eq!(format!('The origin is: {:?}', origin), 'The origin is: Point { x: 0, y: 0 }');n/// ```n///n/// Manually implementing:n///n/// ```n/// use std::fmt;n///n/// struct Point {n/// x: i32,n/// y: i32,n/// }n///n/// impl fmt::Debug for Point {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// f.debug_struct('Point')n/// .field('x', &self.x)n/// .field('y', &self.y)n/// .finish()n/// }n/// }n///n/// let origin = Point { x: 0, y: 0 };n///n/// assert_eq!(format!('The origin is: {:?}', origin), 'The origin is: Point { x: 0, y: 0 }');n/// ```n///n/// There are a number of helper methods on the [`Formatter`] struct to help you with manualn/// implementations, such as [`debug_struct`].n///n/// `Debug` implementations using either `derive` or the debug builder APIn/// on [`Formatter`] support pretty-printing using the alternate flag: `{:#?}`.n///n/// [`debug_struct`]: ../../std/fmt/struct.Formatter.html#method.debug_structn/// [`Formatter`]: ../../std/fmt/struct.Formatter.htmln///n/// Pretty-printing with `#?`:n///n/// ```n/// #[derive(Debug)]n/// struct Point {n/// x: i32,n/// y: i32,n/// }n///n/// let origin = Point { x: 0, y: 0 };n///n/// assert_eq!(format!('The origin is: {:#?}', origin),n/// 'The origin is: Point {n/// x: 0,n/// y: 0,n/// }');n/// ```nn#[stable(feature = 'rust1', since = '1.0.0')]n#[rustc_on_unimplemented(n on(n crate_local,n label = '`{Self}` cannot be formatted using `{{:?}}`',n note = 'add `#[derive(Debug)]` or manually implement `{Debug}`'n ),n message = '`{Self}` doesn't implement `{Debug}`',n label = '`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`'n)]n#[doc(alias = '{:?}')]n#[rustc_diagnostic_item = 'debug_trait']npub trait Debug {n /// Formats the value using the given formatter.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Position {n /// longitude: f32,n /// latitude: f32,n /// }n ///n /// impl fmt::Debug for Position {n /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n /// f.debug_tuple('')n /// .field(&self.longitude)n /// .field(&self.latitude)n /// .finish()n /// }n /// }n ///n /// let position = Position { longitude: 1.987, latitude: 2.983 };n /// assert_eq!(format!('{:?}', position), '(1.987, 2.983)');n ///n /// assert_eq!(format!('{:#?}', position), '(n /// 1.987,n /// 2.983,n /// )');n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn// Separate module to reexport the macro `Debug` from prelude without the trait `Debug`.npub(crate) mod macros {n /// Derive macro generating an impl of the trait `Debug`.n #[rustc_builtin_macro]n #[stable(feature = 'builtin_macro_prelude', since = '1.38.0')]n #[allow_internal_unstable(core_intrinsics)]n pub macro Debug($item:item) {n /* compiler built-in */n }n}n#[stable(feature = 'builtin_macro_prelude', since = '1.38.0')]n#[doc(inline)]npub use macros::Debug;nn/// Format trait for an empty format, `{}`.n///n/// `Display` is similar to [`Debug`][debug], but `Display` is for user-facingn/// output, and so cannot be derived.n///n/// [debug]: trait.Debug.htmln///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// # Examplesn///n/// Implementing `Display` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Point {n/// x: i32,n/// y: i32,n/// }n///n/// impl fmt::Display for Point {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// write!(f, '({}, {})', self.x, self.y)n/// }n/// }n///n/// let origin = Point { x: 0, y: 0 };n///n/// assert_eq!(format!('The origin is: {}', origin), 'The origin is: (0, 0)');n/// ```n#[rustc_on_unimplemented(n on(n _Self = 'std::path::Path',n label = '`{Self}` cannot be formatted with the default formatter; call `.display()` on it',n note = 'call `.display()` or `.to_string_lossy()` to safely print paths, n as they may contain non-Unicode data'n ),n message = '`{Self}` doesn't implement `{Display}`',n label = '`{Self}` cannot be formatted with the default formatter',n note = 'in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead'n)]n#[doc(alias = '{}')]n#[stable(feature = 'rust1', since = '1.0.0')]npub trait Display {n /// Formats the value using the given formatter.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Position {n /// longitude: f32,n /// latitude: f32,n /// }n ///n /// impl fmt::Display for Position {n /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n /// write!(f, '({}, {})', self.longitude, self.latitude)n /// }n /// }n ///n /// assert_eq!('(1.987, 2.983)',n /// format!('{}', Position { longitude: 1.987, latitude: 2.983, }));n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// `o` formatting.n///n/// The `Octal` trait should format its output as a number in base-8.n///n/// For primitive signed integers (`i8` to `i128`, and `isize`),n/// negative values are formatted as the two_s complement representation.n///n/// The alternate flag, `#`, adds a `0o` in front of the output.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// # Examplesn///n/// Basic usage with `i32`:n///n/// ```n/// let x = 42; // 42 is '52' in octaln///n/// assert_eq!(format!('{:o}', x), '52');n/// assert_eq!(format!('{:#o}', x), '0o52');n///n/// assert_eq!(format!('{:o}', -16), '37777777760');n/// ```n///n/// Implementing `Octal` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Length(i32);n///n/// impl fmt::Octal for Length {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// let val = self.0;n///n/// fmt::Octal::fmt(&val, f) // delegate to i32's implementationn/// }n/// }n///n/// let l = Length(9);n///n/// assert_eq!(format!('l as octal is: {:o}', l), 'l as octal is: 11');n///n/// assert_eq!(format!('l as octal is: {:#06o}', l), 'l as octal is: 0o0011');n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]npub trait Octal {n /// Formats the value using the given formatter.n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// `b` formatting.n///n/// The `Binary` trait should format its output as a number in binary.n///n/// For primitive signed integers ([`i8`] to [`i128`], and [`isize`]),n/// negative values are formatted as the two_s complement representation.n///n/// The alternate flag, `#`, adds a `0b` in front of the output.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// # Examplesn///n/// Basic usage with [`i32`]:n///n/// ```n/// let x = 42; // 42 is '101010' in binaryn///n/// assert_eq!(format!('{:b}', x), '101010');n/// assert_eq!(format!('{:#b}', x), '0b101010');n///n/// assert_eq!(format!('{:b}', -16), '11111111111111111111111111110000');n/// ```n///n/// Implementing `Binary` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Length(i32);n///n/// impl fmt::Binary for Length {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// let val = self.0;n///n/// fmt::Binary::fmt(&val, f) // delegate to i32's implementationn/// }n/// }n///n/// let l = Length(107);n///n/// assert_eq!(format!('l as binary is: {:b}', l), 'l as binary is: 1101011');n///n/// assert_eq!(n/// format!('l as binary is: {:#032b}', l),n/// 'l as binary is: 0b000000000000000000000001101011'n/// );n/// ```n///n/// [module]: ../../std/fmt/index.htmln/// [`i8`]: ../../std/primitive.i8.htmln/// [`i128`]: ../../std/primitive.i128.htmln/// [`isize`]: ../../std/primitive.isize.htmln/// [`i32`]: ../../std/primitive.i32.htmln#[stable(feature = 'rust1', since = '1.0.0')]npub trait Binary {n /// Formats the value using the given formatter.n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// `x` formatting.n///n/// The `LowerHex` trait should format its output as a number in hexadecimal, with `a` through `f`n/// in lower case.n///n/// For primitive signed integers (`i8` to `i128`, and `isize`),n/// negative values are formatted as the two_s complement representation.n///n/// The alternate flag, `#`, adds a `0x` in front of the output.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// # Examplesn///n/// Basic usage with `i32`:n///n/// ```n/// let x = 42; // 42 is '2a' in hexn///n/// assert_eq!(format!('{:x}', x), '2a');n/// assert_eq!(format!('{:#x}', x), '0x2a');n///n/// assert_eq!(format!('{:x}', -16), 'fffffff0');n/// ```n///n/// Implementing `LowerHex` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Length(i32);n///n/// impl fmt::LowerHex for Length {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// let val = self.0;n///n/// fmt::LowerHex::fmt(&val, f) // delegate to i32's implementationn/// }n/// }n///n/// let l = Length(9);n///n/// assert_eq!(format!('l as hex is: {:x}', l), 'l as hex is: 9');n///n/// assert_eq!(format!('l as hex is: {:#010x}', l), 'l as hex is: 0x00000009');n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]npub trait LowerHex {n /// Formats the value using the given formatter.n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// `X` formatting.n///n/// The `UpperHex` trait should format its output as a number in hexadecimal, with `A` through `F`n/// in upper case.n///n/// For primitive signed integers (`i8` to `i128`, and `isize`),n/// negative values are formatted as the two_s complement representation.n///n/// The alternate flag, `#`, adds a `0x` in front of the output.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// # Examplesn///n/// Basic usage with `i32`:n///n/// ```n/// let x = 42; // 42 is '2A' in hexn///n/// assert_eq!(format!('{:X}', x), '2A');n/// assert_eq!(format!('{:#X}', x), '0x2A');n///n/// assert_eq!(format!('{:X}', -16), 'FFFFFFF0');n/// ```n///n/// Implementing `UpperHex` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Length(i32);n///n/// impl fmt::UpperHex for Length {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// let val = self.0;n///n/// fmt::UpperHex::fmt(&val, f) // delegate to i32's implementationn/// }n/// }n///n/// let l = Length(i32::MAX);n///n/// assert_eq!(format!('l as hex is: {:X}', l), 'l as hex is: 7FFFFFFF');n///n/// assert_eq!(format!('l as hex is: {:#010X}', l), 'l as hex is: 0x7FFFFFFF');n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]npub trait UpperHex {n /// Formats the value using the given formatter.n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// `p` formatting.n///n/// The `Pointer` trait should format its output as a memory location. This is commonly presentedn/// as hexadecimal.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// # Examplesn///n/// Basic usage with `&i32`:n///n/// ```n/// let x = &42;n///n/// let address = format!('{:p}', x); // this produces something like '0x7f06092ac6d0'n/// ```n///n/// Implementing `Pointer` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Length(i32);n///n/// impl fmt::Pointer for Length {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// // use `as` to convert to a `*const T`, which implements Pointer, which we can usen///n/// let ptr = self as *const Self;n/// fmt::Pointer::fmt(&ptr, f)n/// }n/// }n///n/// let l = Length(42);n///n/// println!('l is in memory here: {:p}', l);n///n/// let l_ptr = format!('{:018p}', l);n/// assert_eq!(l_ptr.len(), 18);n/// assert_eq!(&l_ptr[..2], '0x');n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]npub trait Pointer {n /// Formats the value using the given formatter.n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// `e` formatting.n///n/// The `LowerExp` trait should format its output in scientific notation with a lower-case `e`.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// # Examplesn///n/// Basic usage with `f64`:n///n/// ```n/// let x = 42.0; // 42.0 is '4.2e1' in scientific notationn///n/// assert_eq!(format!('{:e}', x), '4.2e1');n/// ```n///n/// Implementing `LowerExp` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Length(i32);n///n/// impl fmt::LowerExp for Length {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// let val = f64::from(self.0);n/// fmt::LowerExp::fmt(&val, f) // delegate to f64's implementationn/// }n/// }n///n/// let l = Length(100);n///n/// assert_eq!(n/// format!('l in scientific notation is: {:e}', l),n/// 'l in scientific notation is: 1e2'n/// );n///n/// assert_eq!(n/// format!('l in scientific notation is: {:05e}', l),n/// 'l in scientific notation is: 001e2'n/// );n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]npub trait LowerExp {n /// Formats the value using the given formatter.n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// `E` formatting.n///n/// The `UpperExp` trait should format its output in scientific notation with an upper-case `E`.n///n/// For more information on formatters, see [the module-level documentation][module].n///n/// [module]: ../../std/fmt/index.htmln///n/// # Examplesn///n/// Basic usage with `f64`:n///n/// ```n/// let x = 42.0; // 42.0 is '4.2E1' in scientific notationn///n/// assert_eq!(format!('{:E}', x), '4.2E1');n/// ```n///n/// Implementing `UpperExp` on a type:n///n/// ```n/// use std::fmt;n///n/// struct Length(i32);n///n/// impl fmt::UpperExp for Length {n/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n/// let val = f64::from(self.0);n/// fmt::UpperExp::fmt(&val, f) // delegate to f64's implementationn/// }n/// }n///n/// let l = Length(100);n///n/// assert_eq!(n/// format!('l in scientific notation is: {:E}', l),n/// 'l in scientific notation is: 1E2'n/// );n///n/// assert_eq!(n/// format!('l in scientific notation is: {:05E}', l),n/// 'l in scientific notation is: 001E2'n/// );n/// ```n#[stable(feature = 'rust1', since = '1.0.0')]npub trait UpperExp {n /// Formats the value using the given formatter.n #[stable(feature = 'rust1', since = '1.0.0')]n fn fmt(&self, f: &mut Formatter<'_>) -> Result;n}nn/// The `write` function takes an output stream, and an `Arguments` structn/// that can be precompiled with the `format_args!` macro.n///n/// The arguments will be formatted according to the specified format stringn/// into the output stream provided.n///n/// # Examplesn///n/// Basic usage:n///n/// ```n/// use std::fmt;n///n/// let mut output = String::new();n/// fmt::write(&mut output, format_args!('Hello {}!', 'world'))n/// .expect('Error occurred while trying to write in String');n/// assert_eq!(output, 'Hello world!');n/// ```n///n/// Please note that using [`write!`] might be preferable. Example:n///n/// ```n/// use std::fmt::Write;n///n/// let mut output = String::new();n/// write!(&mut output, 'Hello {}!', 'world')n/// .expect('Error occurred while trying to write in String');n/// assert_eq!(output, 'Hello world!');n/// ```n///n/// [`write!`]: ../../std/macro.write.htmln#[stable(feature = 'rust1', since = '1.0.0')]npub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {n let mut formatter = Formatter {n flags: 0,n width: None,n precision: None,n buf: output,n align: rt::v1::Alignment::Unknown,n fill: ' ',n };nn let mut idx = 0;nn match args.fmt {n None => {n // We can use default formatting parameters for all arguments.n for (arg, piece) in args.args.iter().zip(args.pieces.iter()) {n formatter.buf.write_str(*piece)?;n (arg.formatter)(arg.value, &mut formatter)?;n idx += 1;n }n }n Some(fmt) => {n // Every spec has a corresponding argument that is preceded byn // a string piece.n for (arg, piece) in fmt.iter().zip(args.pieces.iter()) {n formatter.buf.write_str(*piece)?;n run(&mut formatter, arg, &args.args)?;n idx += 1;n }n }n }nn // There can be only one trailing string piece left.n if let Some(piece) = args.pieces.get(idx) {n formatter.buf.write_str(*piece)?;n }nn Ok(())n}nnfn run(fmt: &mut Formatter<'_>, arg: &rt::v1::Argument, args: &[ArgumentV1<'_>]) -> Result {n fmt.fill = arg.format.fill;n fmt.align = arg.format.align;n fmt.flags = arg.format.flags;n fmt.width = getcount(args, &arg.format.width);n fmt.precision = getcount(args, &arg.format.precision);nn // Extract the correct argumentn let value = args[arg.position];nn // Then actually do some printingn (value.formatter)(value.value, fmt)n}nnfn getcount(args: &[ArgumentV1<'_>], cnt: &rt::v1::Count) -> Option<usize> {n match *cnt {n rt::v1::Count::Is(n) => Some(n),n rt::v1::Count::Implied => None,n rt::v1::Count::Param(i) => args[i].as_usize(),n }n}nn/// Padding after the end of something. Returned by `Formatter::padding`.n#[must_use = 'don't forget to write the post padding']nstruct PostPadding {n fill: char,n padding: usize,n}nnimpl PostPadding {n fn new(fill: char, padding: usize) -> PostPadding {n PostPadding { fill, padding }n }nn /// Write this post padding.n fn write(self, buf: &mut dyn Write) -> Result {n for _ in 0..self.padding {n buf.write_char(self.fill)?;n }n Ok(())n }n}nnimpl<'a> Formatter<'a> {n fn wrap_buf<'b, 'c, F>(&'b mut self, wrap: F) -> Formatter<'c>n wheren 'b: 'c,n F: FnOnce(&'b mut (dyn Write + 'b)) -> &'c mut (dyn Write + 'c),n {n Formatter {n // We want to change thisn buf: wrap(self.buf),nn // And preserve thesen flags: self.flags,n fill: self.fill,n align: self.align,n width: self.width,n precision: self.precision,n }n }nn // Helper methods used for padding and processing formatting arguments thatn // all formatting traits can use.nn /// Performs the correct padding for an integer which has already beenn /// emitted into a str. The str should *not* contain the sign for then /// integer, that will be added by this method.n ///n /// # Argumentsn ///n /// * is_nonnegative - whether the original integer was either positive or zero.n /// * prefix - if the '#' character (Alternate) is provided, thisn /// is the prefix to put in front of the number.n /// * buf - the byte array that the number has been formatted inton ///n /// This function will correctly account for the flags provided as well asn /// the minimum width. It will not take precision into account.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo { nb: i32 };n ///n /// impl Foo {n /// fn new(nb: i32) -> Foo {n /// Foo {n /// nb,n /// }n /// }n /// }n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// // We need to remove '-' from the number output.n /// let tmp = self.nb.abs().to_string();n ///n /// formatter.pad_integral(self.nb > 0, 'Foo ', &tmp)n /// }n /// }n ///n /// assert_eq!(&format!('{}', Foo::new(2)), '2');n /// assert_eq!(&format!('{}', Foo::new(-1)), '-1');n /// assert_eq!(&format!('{:#}', Foo::new(-1)), '-Foo 1');n /// assert_eq!(&format!('{:0>#8}', Foo::new(-1)), '00-Foo 1');n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n pub fn pad_integral(&mut self, is_nonnegative: bool, prefix: &str, buf: &str) -> Result {n let mut width = buf.len();nn let mut sign = None;n if !is_nonnegative {n sign = Some('-');n width += 1;n } else if self.sign_plus() {n sign = Some('+');n width += 1;n }nn let prefix = if self.alternate() {n width += prefix.chars().count();n Some(prefix)n } else {n Nonen };nn // Writes the sign if it exists, and then the prefix if it was requestedn #[inline(never)]n fn write_prefix(f: &mut Formatter<'_>, sign: Option<char>, prefix: Option<&str>) -> Result {n if let Some(c) = sign {n f.buf.write_char(c)?;n }n if let Some(prefix) = prefix { f.buf.write_str(prefix) } else { Ok(()) }n }nn // The `width` field is more of a `min-width` parameter at this point.n match self.width {n // If there's no minimum length requirements then we can justn // write the bytes.n None => {n write_prefix(self, sign, prefix)?;n self.buf.write_str(buf)n }n // Check if we're over the minimum width, if so then we can alson // just write the bytes.n Some(min) if width >= min => {n write_prefix(self, sign, prefix)?;n self.buf.write_str(buf)n }n // The sign and prefix goes before the padding if the fill charactern // is zeron Some(min) if self.sign_aware_zero_pad() => {n let old_fill = crate::mem::replace(&mut self.fill, '0');n let old_align = crate::mem::replace(&mut self.align, rt::v1::Alignment::Right);n write_prefix(self, sign, prefix)?;n let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?;n self.buf.write_str(buf)?;n post_padding.write(self.buf)?;n self.fill = old_fill;n self.align = old_align;n Ok(())n }n // Otherwise, the sign and prefix goes after the paddingn Some(min) => {n let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?;n write_prefix(self, sign, prefix)?;n self.buf.write_str(buf)?;n post_padding.write(self.buf)n }n }n }nn /// This function takes a string slice and emits it to the internal buffern /// after applying the relevant formatting flags specified. The flagsn /// recognized for generic strings are:n ///n /// * width - the minimum width of what to emitn /// * fill/align - what to emit and where to emit it if the stringn /// provided needs to be paddedn /// * precision - the maximum length to emit, the string is truncated if itn /// is longer than this lengthn ///n /// Notably this function ignores the `flag` parameters.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo;n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// formatter.pad('Foo')n /// }n /// }n ///n /// assert_eq!(&format!('{:<4}', Foo), 'Foo ');n /// assert_eq!(&format!('{:0>4}', Foo), '0Foo');n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n pub fn pad(&mut self, s: &str) -> Result {n // Make sure there's a fast path up frontn if self.width.is_none() && self.precision.is_none() {n return self.buf.write_str(s);n }n // The `precision` field can be interpreted as a `max-width` for then // string being formatted.n let s = if let Some(max) = self.precision {n // If our string is longer that the precision, then we must haven // truncation. However other flags like `fill`, `width` and `align`n // must act as always.n if let Some((i, _)) = s.char_indices().nth(max) {n // LLVM here can't prove that `..i` won't panic `&s[..i]`, butn // we know that it can't panic. Use `get` + `unwrap_or` to avoidn // `unsafe` and otherwise don't emit any panic-related coden // here.n s.get(..i).unwrap_or(&s)n } else {n &sn }n } else {n &sn };n // The `width` field is more of a `min-width` parameter at this point.n match self.width {n // If we're under the maximum length, and there's no minimum lengthn // requirements, then we can just emit the stringn None => self.buf.write_str(s),n // If we're under the maximum width, check if we're over the minimumn // width, if so it's as easy as just emitting the string.n Some(width) if s.chars().count() >= width => self.buf.write_str(s),n // If we're under both the maximum and the minimum width, then filln // up the minimum width with the specified string + some alignment.n Some(width) => {n let align = rt::v1::Alignment::Left;n let post_padding = self.padding(width - s.chars().count(), align)?;n self.buf.write_str(s)?;n post_padding.write(self.buf)n }n }n }nn /// Write the pre-padding and return the unwritten post-padding. Callers aren /// responsible for ensuring post-padding is written after the thing that isn /// being padded.n fn padding(n &mut self,n padding: usize,n default: rt::v1::Alignment,n ) -> result::Result<PostPadding, Error> {n let align = match self.align {n rt::v1::Alignment::Unknown => default,n _ => self.align,n };nn let (pre_pad, post_pad) = match align {n rt::v1::Alignment::Left => (0, padding),n rt::v1::Alignment::Right | rt::v1::Alignment::Unknown => (padding, 0),n rt::v1::Alignment::Center => (padding / 2, (padding + 1) / 2),n };nn for _ in 0..pre_pad {n self.buf.write_char(self.fill)?;n }nn Ok(PostPadding::new(self.fill, post_pad))n }nn /// Takes the formatted parts and applies the padding.n /// Assumes that the caller already has rendered the parts with required precision,n /// so that `self.precision` can be ignored.n fn pad_formatted_parts(&mut self, formatted: &flt2dec::Formatted<'_>) -> Result {n if let Some(mut width) = self.width {n // for the sign-aware zero padding, we render the sign first andn // behave as if we had no sign from the beginning.n let mut formatted = formatted.clone();n let old_fill = self.fill;n let old_align = self.align;n let mut align = old_align;n if self.sign_aware_zero_pad() {n // a sign always goes firstn let sign = formatted.sign;n self.buf.write_str(sign)?;nn // remove the sign from the formatted partsn formatted.sign = '';n width = width.saturating_sub(sign.len());n align = rt::v1::Alignment::Right;n self.fill = '0';n self.align = rt::v1::Alignment::Right;n }nn // remaining parts go through the ordinary padding process.n let len = formatted.len();n let ret = if width <= len {n // no paddingn self.write_formatted_parts(&formatted)n } else {n let post_padding = self.padding(width - len, align)?;n self.write_formatted_parts(&formatted)?;n post_padding.write(self.buf)n };n self.fill = old_fill;n self.align = old_align;n retn } else {n // this is the common case and we take a shortcutn self.write_formatted_parts(formatted)n }n }nn fn write_formatted_parts(&mut self, formatted: &flt2dec::Formatted<'_>) -> Result {n fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result {n // SAFETY: This is used for `flt2dec::Part::Num` and `flt2dec::Part::Copy`.n // It's safe to use for `flt2dec::Part::Num` since every char `c` is betweenn // `b'0'` and `b'9'`, which means `s` is valid UTF-8.n // It's also probably safe in practice to use for `flt2dec::Part::Copy(buf)`n // since `buf` should be plain ASCII, but it's possible for someone to passn // in a bad value for `buf` into `flt2dec::to_shortest_str` since it is an // public function.n // FIXME: Determine whether this could result in UB.n buf.write_str(unsafe { str::from_utf8_unchecked(s) })n }nn if !formatted.sign.is_empty() {n self.buf.write_str(formatted.sign)?;n }n for part in formatted.parts {n match *part {n flt2dec::Part::Zero(mut nzeroes) => {n const ZEROES: &str = // 64 zeroesn '0000000000000000000000000000000000000000000000000000000000000000';n while nzeroes > ZEROES.len() {n self.buf.write_str(ZEROES)?;n nzeroes -= ZEROES.len();n }n if nzeroes > 0 {n self.buf.write_str(&ZEROES[..nzeroes])?;n }n }n flt2dec::Part::Num(mut v) => {n let mut s = [0; 5];n let len = part.len();n for c in s[..len].iter_mut().rev() {n *c = b'0' + (v % 10) as u8;n v /= 10;n }n write_bytes(self.buf, &s[..len])?;n }n flt2dec::Part::Copy(buf) => {n write_bytes(self.buf, buf)?;n }n }n }n Ok(())n }nn /// Writes some data to the underlying buffer contained within thisn /// formatter.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo;n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// formatter.write_str('Foo')n /// // This is equivalent to:n /// // write!(formatter, 'Foo')n /// }n /// }n ///n /// assert_eq!(&format!('{}', Foo), 'Foo');n /// assert_eq!(&format!('{:0>8}', Foo), 'Foo');n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n pub fn write_str(&mut self, data: &str) -> Result {n self.buf.write_str(data)n }nn /// Writes some formatted information into this instance.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo(i32);n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// formatter.write_fmt(format_args!('Foo {}', self.0))n /// }n /// }n ///n /// assert_eq!(&format!('{}', Foo(-1)), 'Foo -1');n /// assert_eq!(&format!('{:0>8}', Foo(2)), 'Foo 2');n /// ```n #[stable(feature = 'rust1', since = '1.0.0')]n pub fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result {n write(self.buf, fmt)n }nn /// Flags for formattingn #[stable(feature = 'rust1', since = '1.0.0')]n #[rustc_deprecated(n since = '1.24.0',n reason = 'use the `sign_plus`, `sign_minus`, `alternate`, n or `sign_aware_zero_pad` methods instead'n )]n pub fn flags(&self) -> u32 {n self.flagsn }nn /// Character used as 'fill' whenever there is alignment.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo;n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// let c = formatter.fill();n /// if let Some(width) = formatter.width() {n /// for _ in 0..width {n /// write!(formatter, '{}', c)?;n /// }n /// Ok(())n /// } else {n /// write!(formatter, '{}', c)n /// }n /// }n /// }n ///n /// // We set alignment to the left with '>'.n /// assert_eq!(&format!('{:G>3}', Foo), 'GGG');n /// assert_eq!(&format!('{:t>6}', Foo), 'tttttt');n /// ```n #[stable(feature = 'fmt_flags', since = '1.5.0')]n pub fn fill(&self) -> char {n self.filln }nn /// Flag indicating what form of alignment was requested.n ///n /// # Examplesn ///n /// ```n /// extern crate core;n ///n /// use std::fmt::{self, Alignment};n ///n /// struct Foo;n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// let s = if let Some(s) = formatter.align() {n /// match s {n /// Alignment::Left => 'left',n /// Alignment::Right => 'right',n /// Alignment::Center => 'center',n /// }n /// } else {n /// 'into the void'n /// };n /// write!(formatter, '{}', s)n /// }n /// }n ///n /// assert_eq!(&format!('{:<}', Foo), 'left');n /// assert_eq!(&format!('{:>}', Foo), 'right');n /// assert_eq!(&format!('{:^}', Foo), 'center');n /// assert_eq!(&format!('{}', Foo), 'into the void');n /// ```n #[stable(feature = 'fmt_flags_align', since = '1.28.0')]n pub fn align(&self) -> Option<Alignment> {n match self.align {n rt::v1::Alignment::Left => Some(Alignment::Left),n rt::v1::Alignment::Right => Some(Alignment::Right),n rt::v1::Alignment::Center => Some(Alignment::Center),n rt::v1::Alignment::Unknown => None,n }n }nn /// Optionally specified integer width that the output should be.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo(i32);n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// if let Some(width) = formatter.width() {n /// // If we received a width, we use itn /// write!(formatter, '{:width$}', &format!('Foo({})', self.0), width = width)n /// } else {n /// // Otherwise we do nothing specialn /// write!(formatter, 'Foo({})', self.0)n /// }n /// }n /// }n ///n /// assert_eq!(&format!('{:10}', Foo(23)), 'Foo(23) ');n /// assert_eq!(&format!('{}', Foo(23)), 'Foo(23)');n /// ```n #[stable(feature = 'fmt_flags', since = '1.5.0')]n pub fn width(&self) -> Option<usize> {n self.widthn }nn /// Optionally specified precision for numeric types. Alternatively, then /// maximum width for string types.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo(f32);n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// if let Some(precision) = formatter.precision() {n /// // If we received a precision, we use it.n /// write!(formatter, 'Foo({1:.*})', precision, self.0)n /// } else {n /// // Otherwise we default to 2.n /// write!(formatter, 'Foo({:.2})', self.0)n /// }n /// }n /// }n ///n /// assert_eq!(&format!('{:.4}', Foo(23.2)), 'Foo(23.2000)');n /// assert_eq!(&format!('{}', Foo(23.2)), 'Foo(23.20)');n /// ```n #[stable(feature = 'fmt_flags', since = '1.5.0')]n pub fn precision(&self) -> Option<usize> {n self.precisionn }nn /// Determines if the `+` flag was specified.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo(i32);n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// if formatter.sign_plus() {n /// write!(formatter,n /// 'Foo({}{})',n /// if self.0 < 0 { '-' } else { '+' },n /// self.0)n /// } else {n /// write!(formatter, 'Foo({})', self.0)n /// }n /// }n /// }n ///n /// assert_eq!(&format!('{:+}', Foo(23)), 'Foo(+23)');n /// assert_eq!(&format!('{}', Foo(23)), 'Foo(23)');n /// ```n #[stable(feature = 'fmt_flags', since = '1.5.0')]n pub fn sign_plus(&self) -> bool {n self.flags & (1 << FlagV1::SignPlus as u32) != 0n }nn /// Determines if the `-` flag was specified.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo(i32);n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// if formatter.sign_minus() {n /// // You want a minus sign? Have one!n /// write!(formatter, '-Foo({})', self.0)n /// } else {n /// write!(formatter, 'Foo({})', self.0)n /// }n /// }n /// }n ///n /// assert_eq!(&format!('{:-}', Foo(23)), '-Foo(23)');n /// assert_eq!(&format!('{}', Foo(23)), 'Foo(23)');n /// ```n #[stable(feature = 'fmt_flags', since = '1.5.0')]n pub fn sign_minus(&self) -> bool {n self.flags & (1 << FlagV1::SignMinus as u32) != 0n }nn /// Determines if the `#` flag was specified.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo(i32);n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// if formatter.alternate() {n /// write!(formatter, 'Foo({})', self.0)n /// } else {n /// write!(formatter, '{}', self.0)n /// }n /// }n /// }n ///n /// assert_eq!(&format!('{:#}', Foo(23)), 'Foo(23)');n /// assert_eq!(&format!('{}', Foo(23)), '23');n /// ```n #[stable(feature = 'fmt_flags', since = '1.5.0')]n pub fn alternate(&self) -> bool {n self.flags & (1 << FlagV1::Alternate as u32) != 0n }nn /// Determines if the `0` flag was specified.n ///n /// # Examplesn ///n /// ```n /// use std::fmt;n ///n /// struct Foo(i32);n ///n /// impl fmt::Display for Foo {n /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {n /// assert!(formatter.sign_aware_zero_pad());n /// assert_eq!(formatter.width(), Some(4));n /// // We ignore the formatter's options.n /// write!(formatter, '{}', self.0)n /// }n /// }n ///n /// assert_eq!(&format!('{:04}', Foo(23)), '23');n /// ```n #[stable(feature = 'fmt_flags', since = '1.5.0')]n pub fn sign_aware_zero_pad(&self) -> bool {n self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0n }nn // FIXME: Decide what public API we want for these two flags.n // https://github.com/rust-lang/rust/issues/48584n fn debug_lower_hex(&self) -> bool {n self.flags & (1 << FlagV1::DebugLowerHex as u32) != 0n }nn fn debug_upper_hex(&self) -> bool {n self.flags & (1 << FlagV1::DebugUpperHex as u32) != 0n }nn /// Creates a [`DebugStruct`] builder designed to assist with creation ofn /// [`fmt::Debug`] implementations for structs.n ///n /// [`DebugStruct`]: ../../std/fmt/struct.DebugStruct.htmln /// [`fmt::Debug`]: ../../std/fmt/trait.Debug.htmln ///n /// # Examplesn ///n /// ```rustn /// use std::fmt;n /// use std::net::Ipv4Addr;n ///n /// struct Foo {n /// bar: i32,n /// baz: String,n /// addr: Ipv4Addr,n /// }n ///n /// impl fmt::Debug for Foo {n /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {n /// fmt.debug_struct('Foo')n /// .field('bar', &self.bar)n /// .field('baz', &self.baz)n /// .field('addr', &format_args!('{}', self.addr))n /// .finish()n /// }n /// }n ///n /// assert_eq!(n /// 'Foo { bar: 10, baz: 'Hello World', addr: 127.0.0.1 }',n /// format!('{:?}', Foo {n /// bar: 10,n /// baz: 'Hello World'.to_string(),n /// addr: Ipv4Addr::new(127, 0, 0, 1),n /// })n /// );n /// ```n #[stable(feature = 'debug_builders', since = '1.2.0')]n pub fn debug_struct<'b>(&'b mut self, name: &str) -> DebugStruct<'b, 'a> {n builders::debug_struct_new(self, name)n }nn /// Creates a `DebugTuple` builder designed to assist with creation ofn /// `fmt::Debug` implementations for tuple structs.n ///n /// # Examplesn ///n /// ```rustn /// use std::fmt;n /// use std::marker::PhantomData;n ///n /// struct Foo<T>(i32, String, PhantomData<T>);n ///n /// impl<T> fmt::Debug for Foo<T> {n /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {n /// fmt.debug_tuple('Foo')n /// .field(&self.0)n /// .field(&self.1)n /// .field(&format_args!('_'))n /// .finish()n /// }n /// }n ///n /// assert_eq!(n /// 'Foo(10, 'Hello', _)',n /// format!('{:?}', Foo(10, 'Hello'.to_string(), PhantomData::<u8>))n /// );n /// ```n #[stable(feature = 'debug_builders', since = '1.2.0')]n pub fn debug_tuple<'b>(&'b mut self, name: &str) -> DebugTuple<'b, 'a> {n builders::debug_tuple_new(self, name)n }nn /// Creates a `DebugList` builder designed to assist with creation ofn /// `fmt::Debug` implementations for list-like structures.n ///n /// # Examplesn ///n /// ```rustn /// use std::fmt;n ///n /// struct Foo(Vec<i32>);n ///n /// impl fmt::Debug for Foo {n /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {n /// fmt.debug_list().entries(self.0.iter()).finish()n /// }n /// }n ///n /// assert_eq!(format!('{:?}', Foo(vec![10, 11])), '[10, 11]');n /// ```n #[stable(feature = 'debug_builders', since = '1.2.0')]n pub fn debug_list<'b>(&'b mut self) -> DebugList<'b, 'a> {n builders::debug_list_new(self)n }nn /// Creates a `DebugSet` builder designed to assist with creation ofn /// `fmt::Debug` implementations for set-like structures.n ///n /// # Examplesn ///n /// ```rustn /// use std::fmt;n ///n /// struct Foo(Vec<i32>);n ///n /// impl fmt::Debug for Foo {n /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {n /// fmt.debug_set().entries(self.0.iter()).finish()n /// }n /// }n ///n /// assert_eq!(format!('{:?}', Foo(vec![10, 11])), '{10, 11}');n /// ```n ///n /// [`format_args!`]: ../../std/macro.format_args.htmln ///n /// In this more complex example, we use [`format_args!`] and `.debug_set()`n /// to build a list of match arms:n ///n /// ```rustn /// use std::fmt;n ///n /// struct Arm<'a, L: 'a, R: 'a>(&'a (L, R));n /// struct Table<'a, K: 'a, V: 'a>(&'a [(K, V)], V);n ///n /// impl<'a, L, R> fmt::Debug for Arm<'a, L, R>n /// wheren /// L: 'a + fmt::Debug, R: 'a + fmt::Debugn /// {n /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {n /// L::fmt(&(self.0).0, fmt)?;n /// fmt.write_str(' => ')?;n /// R::fmt(&(self.0).1, fmt)n /// }n /// }n ///n /// impl<'a, K, V> fmt::Debug for Table<'a, K, V>n /// wheren /// K: 'a + fmt::Debug, V: 'a + fmt::Debugn /// {n /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {n /// fmt.debug_set()n /// .entries(self.0.iter().map(Arm))n /// .entry(&Arm(&(format_args!('_'), &self.1)))n /// .finish()n /// }n /// }n /// ```n #[stable(feature = 'debug_builders', since = '1.2.0')]n pub fn debug_set<'b>(&'b mut self) -> DebugSet<'b, 'a> {n builders::debug_set_new(self)n }nn /// Creates a `DebugMap` builder designed to assist with creation ofn /// `fmt::Debug` implementations for map-like structures.n ///n /// # Examplesn ///n /// ```rustn /// use std::fmt;n ///n /// struct Foo(Vec<(String, i32)>);n ///n /// impl fmt::Debug for Foo {n /// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {n /// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish()n /// }n /// }n ///n /// assert_eq!(n /// format!('{:?}', Foo(vec![('A'.to_string(), 10), ('B'.to_string(), 11)])),n /// r#'{'A': 10, 'B': 11}'#n /// );n /// ```n #[stable(feature = 'debug_builders', since = '1.2.0')]n pub fn debug_map<'b>(&'b mut self) -> DebugMap<'b, 'a> {n builders::debug_map_new(self)n }n}nn#[stable(since = '1.2.0', feature = 'formatter_write')]nimpl Write for Formatter<'_> {n fn write_str(&mut self, s: &str) -> Result {n self.buf.write_str(s)n }nn fn write_char(&mut self, c: char) -> Result {n self.buf.write_char(c)n }nn fn write_fmt(&mut self, args: Arguments<'_>) -> Result {n write(self.buf, args)n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Display for Error {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Display::fmt('an error occurred when formatting an argument', f)n }n}nn// Implementations of the core formatting traitsnnmacro_rules! fmt_refs {n ($($tr:ident),*) => {n $(n #[stable(feature = 'rust1', since = '1.0.0')]n impl<T: ?Sized + $tr> $tr for &T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) }n }n #[stable(feature = 'rust1', since = '1.0.0')]n impl<T: ?Sized + $tr> $tr for &mut T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) }n }n )*n }n}nnfmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp }nn#[unstable(feature = 'never_type', issue = '35121')]nimpl Debug for ! {n fn fmt(&self, _: &mut Formatter<'_>) -> Result {n *selfn }n}nn#[unstable(feature = 'never_type', issue = '35121')]nimpl Display for ! {n fn fmt(&self, _: &mut Formatter<'_>) -> Result {n *selfn }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Debug for bool {n #[inline]n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Display::fmt(self, f)n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Display for bool {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Display::fmt(if *self { 'true' } else { 'false' }, f)n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Debug for str {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n f.write_char(''')?;n let mut from = 0;n for (i, c) in self.char_indices() {n let esc = c.escape_debug();n // If char needs escaping, flush backlog so far and write, else skipn if esc.len() != 1 {n f.write_str(&self[from..i])?;n for c in esc {n f.write_char(c)?;n }n from = i + c.len_utf8();n }n }n f.write_str(&self[from..])?;n f.write_char(''')n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Display for str {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n f.pad(self)n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Debug for char {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n f.write_char(''')?;n for c in self.escape_debug() {n f.write_char(c)?n }n f.write_char(''')n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Display for char {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n if f.width.is_none() && f.precision.is_none() {n f.write_char(*self)n } else {n f.pad(self.encode_utf8(&mut [0; 4]))n }n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: ?Sized> Pointer for *const T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n let old_width = f.width;n let old_flags = f.flags;nn // The alternate flag is already treated by LowerHex as being special-n // it denotes whether to prefix with 0x. We use it to work out whethern // or not to zero extend, and then unconditionally set it to get then // prefix.n if f.alternate() {n f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);nn if f.width.is_none() {n f.width = Some(((mem::size_of::<usize>() * 8) / 4) + 2);n }n }n f.flags |= 1 << (FlagV1::Alternate as u32);nn let ret = LowerHex::fmt(&(*self as *const () as usize), f);nn f.width = old_width;n f.flags = old_flags;nn retn }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: ?Sized> Pointer for *mut T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Pointer::fmt(&(*self as *const T), f)n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: ?Sized> Pointer for &T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Pointer::fmt(&(*self as *const T), f)n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: ?Sized> Pointer for &mut T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Pointer::fmt(&(&**self as *const T), f)n }n}nn// Implementation of Display/Debug for various core typesnn#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: ?Sized> Debug for *const T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Pointer::fmt(self, f)n }n}n#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: ?Sized> Debug for *mut T {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n Pointer::fmt(self, f)n }n}nnmacro_rules! peel {n ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* })n}nnmacro_rules! tuple {n () => ();n ( $($name:ident,)+ ) => (n #[stable(feature = 'rust1', since = '1.0.0')]n impl<$($name:Debug),+> Debug for ($($name,)+) where last_type!($($name,)+): ?Sized {n #[allow(non_snake_case, unused_assignments)]n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n let mut builder = f.debug_tuple('');n let ($(ref $name,)+) = *self;n $(n builder.field(&$name);n )+nn builder.finish()n }n }n peel! { $($name,)+ }n )n}nnmacro_rules! last_type {n ($a:ident,) => { $a };n ($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) };n}nntuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: Debug> Debug for [T] {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n f.debug_list().entries(self.iter()).finish()n }n}nn#[stable(feature = 'rust1', since = '1.0.0')]nimpl Debug for () {n #[inline]n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n f.pad('()')n }n}n#[stable(feature = 'rust1', since = '1.0.0')]nimpl<T: ?Sized> Debug for PhantomData<T> {n fn fmt(&self, f: &mut Formatter<'_>) -> Result {n f.pad('PhantomData')n }n}'n'n'''(''t'e'I''v'i'r''I'''''''d'e'z'i'S' ':'' where Self: Sized''e'd'['m''''#'n'HE'''e'IGHT a''s''V't' u8; // c'I'onv''''en''i''e''''T''''''''''''''''''''''''''''''''''I''''''''''''''''.'e'''r'e'''h'impl<C: ListCo''nfig> Copy for 'I'I''tem''Marker'I'<C> {}'impl<C: Lis''tConfig> PartialEq for'm' ItemMarker'e'<C> {' f't'n eq(&self,'I' other: &Self) -> ''bool { self.ptr == ''other.ptr }'}''' '' 'n'' ''''''''''''''''''''d'e'z'i'S'''''''S'L' ':'f'l'e'S' 'e'r'e'h'w' ' '''q'E'''n'' 'n'n'' ''s'''k'}''''r'o'w' 't'''n'Par''tialEq'''''''a'i't'''r'a'''P''n 'fn eq(&self, other: ''''f'l''''''l'o'o'b''''' 'e'''''''''''''''''''''''''' '''r''''// Blanket implementations for some common builtin types, because its impossiblen// to add these later''''''''''''''''''''''''m'e't'i' 'y'r'e'v'e' 'e'k'a'm'''''''''''''impl<X, Y> ListItem for (X, Y) {}nimpl<X, Y, Z> ListItem for (X, Y, Z) {}nimpl<V> ListItem for Option<V> {}nimpl<T, E> ListItem for Result<T, E> {'n'}n''''''''''''''''''''''''&'''''.'1' 'f'o' 'e'z'i's' 'a' 'e'v'a'h'&'''''a' 'g'n'i'h't'y'r'e'v'e' 'e'k''&'a'm''''' 'e's'u'''''''e's''''''''''' '&''h'c'a'e' 'e'k'a'm''impl ListItem for u8 {}nimpl ListItem for i8 {}nimpl ListItem for u16 {}nimpl ListItem for i16 {}nimpl ListIte'impl ListItem for i32 {}'impl ListItem for'''''e'z'i's'u' i32 {}n'n'm'''''e'z'i's'i' for u32 {}nimpl ListItem for i32 {}nimpl ListItem for f32 {}nimpl ListItem for f64 {}'n'n' 'l'l'a' 'e's''&'e'h'T' '''impl ListIte'&'m for () {}'impl<X, Y>'&' ListItem for ('impl ListItem for &i32 {}'impl ListItem for '''''e'z'i's'u'&i32 {}n'n'X,'''''e'z'i's'i' Y) {}'i'&'mpl<X, Y, Z> ListItem for'&' (X, Y, Z) {}'impl<V> Lis'&'tItem for Option<V> {}n'n'&''n''''E' ','T'''''R' ','E'&''''o'''_se'''''''>'E''' ''','''''t'' 'n 'USED'''''d'e's'u''notifications_use''''d''n''(''''del''''t'''e'''u'r't' '=' ')'''''''''i'f'i't'o'n'' const'''n ' foo: bool;' ''T'''''R' ','E''''l'u's'e'R''V'<'o'''_se'''''n''i'''''''''''>'V'n''<'n'o'i't'p'O'''''''Z' ','''''''D'E'S'U''>'Y' ''''d'e's'u'','X'<'''Z' ''','n'''mpl'del''''t'cons''t ''''const notific': bool'ations_use''d: bool ='''''';'e's'l'a'f' true;''''Y' ','''X' Lis'''''t's'n'o''''n'c'tItem for'')'('''n'''' ''u8 {'nimpl ListItem for u8 {}'}n''impl ListItem f'i'''or u8 {''impl ListIt'n 'fn notify_removed(&mut self,'''''''''''''''';')']'m'e't'I'['&''''*' ':'s'm'e't'i'''''''''''''m'e'''n '''''''''''''''';'''','l'o'o'b' ':'o'o'f' 't's'n'o'c' ''t'k''' _' 'em for u16 {}n''}'impl ListItem'i''''s''' f'impl'' ListItem for u32 {}n'or's''' u8 'i'''{}'im's'''pl ListItem''6'1'fn notify_removed(&mut self,'_' items: &[Item]'')'''}'{' ';'''''''''d'e'g'n'a'h'c'_'''' for u8 {}'impl L''2'3''impl ListItem for f32 {''}n'''istIte'n ''''''''''''''_' ','''' 'f'l'e's' 't'u'm'&''''*'('''''''''''''''''d'e'v'o'm'e'r'_'y'f'i't'o'n' 'n'f' 'm for u8 ''4'6'''{'''''2'3'f'''}''n'n'n'n''''''''''''''''''''''''}'{' '8'u' 'r'o'f' 'm'e't'I't's'i'L' 'l'p'm'i'n'.'''''''''''''''''''''''''''''''''''''''''''' 'n'o'm''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'e's'u' 'l'l'a' 'e's'e'h'T' '.'r'e't'a'l' 'e's'e'h't' 'd'd'a' 'o't' 'e'l'b'i's's'o'p'm'i' 's't'i' 'e's'u'a'c'e'b' ',''''''' ';'s'e'p'y't' ''m'o'c' 'e'm'o's''''''''n'i't'l'i'u'b' 'r'o'f' 's'n'o'i't'a't'n'e'm'e'l'p'm'i' 't'e'k'n'a'l'B' '/'/'n'n't'p'''''''''''''>'T'<'''''''''''''''''''T' 'r'o'f' '>'''''e'r'e'h'w''T'''''''''''''}'{' 'd'e'z'i'S' ':'T' '<'''''''''''''' 'r'o'f' 'm'e't'I't's'i'L' 'l'p'm'i''n'n'''.'''r'e'h't'o' '='=' 'r't'p'.'f'l'e's' ''}'{''''S''''''''m'''e'''t'I't's'i'L''ListConfig''''&Rhs) -> bool;' n''o'd' 's't'i'a'r't' 'e'v'i''''''''''' 'l'p'm'i'n'r'e'D' '/'/'n'n''ce.nnpub struct ''''''''m'''l'p'm'i'n'I'e't'''''''e'n 't' '''fn clone('I'&self) -> Sel''''''''''''f'l'e's''''''V'''''}' 'f'l'e's'*' '{''' '''f;''// '''T''''clone''('''m'e't')''''o'l'c''' 'n'f' n''n'o'I''l'C'emMar''''''m'''''''''ListCon'e'fi'>'g''''''''''t''''''m'e'm''t'I't's'i'L' ':''e'I''''n'm'impl<C: 't'ListCon'e'fig> Copy for I't'''m'e't''temMarker<C> {}'I''t's'i'L' ':''''>'C'<'C'''''<''''''''m''''''''V'ListConfig'e''''''t's'i'L' ''':''t''>'C'<''''''''T'''''''''Ite''''''n ''''''default(''''''''I'''I'''''''''m'e't'I't's'''i'L'f'l'e'S'''I''''''f'l'E'S' '>'-' '''''''I'''''''''''''''}' ')'('l'l''m'u'e'''t'n'I'''t':'s'''m''i':'L'''m'' 'f':''l'e''e'S' '{''e' ')'I''''t'''f'e'd' ''t'n'f' '''I''}'n'I' '{' '>'C'<'m'''e'''m't'M'I'a't'r'I'''V'''s'k'i'er'''''''L'M'm'e't'''I' 'r'o'f' 't'l'u''T'a'f'e'D' 'l'p'm'i'n'n'''''''''n'n'''''''''''''I'I'temMarke'''}'{' 'r''''''M'm'''e't'I' 'r'o'f' 'y'p'o'C' 'l'p'm'i'n'n''''''''''''ListConfig'''''t's'i'L' ':'' pu'y'I''''b fn null() -> ItemMarke'm'r<C'e'> {'t'n 'I' 't' 's'Ite'i'mMa'm''L'rke' 'r {':' ptr: pt'e'r::null_mu'm't() }n 'm''t'''I'''n 'e' '}n''>'C'e''''' '''_'t'''m's'i'''''''t''f'l'e''''I''e''l'o'o'b'm'''s'''''''''''t'''''''''''''e')'('l'l'u''I'n'_'s'i'.''V'r't''m''t'p'.'f''''.'l'e's'''''e''''''':''''''''''''s'V''t''i':':'r't'T''p'''&''It'I'emMarke'''''>'C'<'r'''''T'I'''b'u''T'''p''<'''Ite'I''''>'C'<'m'V'M'y'arke'''''' ''' '''n''''''''>'I''''C'<''''ItemMarke'''''''T't'u'm'_''n'' 'I''' 'ItemMarke''''''''''''''''null('''' 'I' }''I'n '' '''' '}' ')''''l'u'''n'm'':':''e'r't'p't'''''''I''''n''t'''// 's'I'''''m'''''''i'r'e''t'P'L''t'' ':'' 'I''r't'p''t':'' ''/'s'/ '{' ''i'r'''''''L'M'm'e''' '// 'm''t'I':'' 'e''{' 'r''''t''I'''m'e''I't'I' '>'-'t'' ')'(''''s'''''(')'f'i''''''l'l''L'u'n'I'' '' '''}''n ':''n '// ' ' '{' 'r'''''m'e't'I' 'l''_'p'm'i''''n'n'n'ke'_'r<'a, C: ListCo'I'nfi'// 'g>'// ' {n ptr: *mut Node<C>,n _phantom: PhantomData<&'a Sk''ipList<C>>n}nn/// The whole list i'''''ListConfig''''''o't's'i'L' ':'C''''''>'m'e't'I'<'s configured through a single generic trait parameternpub trait ''ListConf' '// ''''''''''''''''''''''''''''''t''' /// To turn off bookkeeping rela''':':'C't''ed'pub(super) ' t' '' // fn not'C'';''''''// ''''''''''''''''';'y'''''''''ListConfig'''''t's'i'L' ':''>'''''')'(''''''''NoNotif'''' ''''notifications_use'''''''''''''''''''''n 'fn notify(&mut self, items: &[C::Item], at_marker: ItemMarker<'''}'{' '''C>);' '}' 'e's'l'a'f' '{' 'l'o'o'b' '>'-' ')'('d''''m'''''i'f'i't'o'n' 'n'f' '''e''}''n 'n ' '{' 'y''''t'''o'N'o'N' 'r'o'f' '>'C'<'I'''C'<'''NotificationTarget''''''f'i't'o'''N' 'l'p'm'i''f'i't'o'N'o''V'N'''o''''''''''''''''''''''n'o'i't'a'c'''i'f'i't'o'N'l'l'u''''o'N' 'T''t'c'u'r't's'n''''''''''''''''''o'N'o'N''' 't'i'a'r't' 'b'u'p'n'n'''I''i''';'''fy(&m''ut ''self, _items: &[Se''lf::Item], _at_m''''ListItem''''m''''I't's'i'L' ':''''L'I'arker'e': ItemMarker<Self>) where Sel't'f: Sized {n '' // ''}n'o ItemMarker query lookups. Then /// optimizer will inline this'n '''''''' '''' 't's'n'o'c' '/''''''''''''''''' ''''' ''''''''''''''''''''''''''''r'e'k'r'a'M'm'e't'I' '''''''''''''''''s'p'u'k'o'o'l' 'y'r'e'u'q''''l' 'o't' 'd'e't'a'l'e'r' '''''''''''''''''''''''''''''''''''''''''''s'i'h't' 'e'n'i'l'n'i' 'l'l'i'w' 'r'e'z'''''''r'e'i'm'i't'p'o' 'e''I'h'T' '.'g'n'i'p'e'e'k'k'o'o'b'''''''s'a'r'f'n'i''''''''''''n'i' 'r'e'i'l'p'm'o'c' 'e'm'o's' 'f'f'o' 'n'r'm''u't' 'o''''''' 'u'T''''' 'r'o''e'F' '/'/' 'e'g'r'a'T'n'o'i't'a'''t''''''''''''''''''''''''''''''n 'n ' '}' 'e'u'r't' '{' 'l'o'o'b' '>'-' ')'('''''''-' ''s'c' impl ListItem for Item ''{ }''i'f''''''''''n ''''''''''''''''''''_'n'o'i't'a'c'i'f'i't'''''''i'f'o'n''''_'s'i'''''d'e's'u' 'n'f' '''}'n '{' 'y''''''''''d'e''m'i''''y'f'i't'o'N' 't'i'a'r't' 'b''e'u'p'n'n'' '// 'type Item''; //+ s't'td:''':''':''f''m''t::Debug;n'ig {n type Item; //+ std::fmt::Debug;nn /// Application'I'''s which have custom sizes (or do their ownn /// run-length-encoding) can define their own size function for items. Whenn /// items are inserted or replaced, the position is specified using then /// custom size defined here.n fn get_usersize(_'pub(super) 'item: &Self::Ite'I'''m) -> usize { 1 }nn fn userlen_of_slice(items: &[Self::Item]) -> usize {n items.iter().fold(0, |acc, item| {n acc + Self::get_usersize(item)n 'n '''''''''''''''''';''')'8'''''''''m'e't''''m'''e'''t'I'''''f'l'e's'&'''I't's'i'L'u'('m'e't'I' 't'c'u'r't's''' ' '// ''m'})n }n''n fn split_'// '''ite'e'm(_item: ''''m'e't'I'&Self::Item,'m't'' _''at: usize) '''// '-> (S'e'elf::Item, Self::It'// 'em)'t'''''m'e't'I' {n'// ' 'I' uni''mplemented!('Cannot insert in the'' ''middle o'// 'f an i'// 'tem 'V'- split_item is not defined in trait');n '' }nn //'// ' fn notify(&'T'mut self, _items: &[Self::Item], _at_marke''r: ItemMarker<Self>) where S'I'elf: Sized {n // }n n}nnpub trait Qu''eryable {n type Query;nn // Returns So'I'''me('ListItem'''''t's'i'L'I''''offset) into the item if its contained. Otherwise None.n fn contains_item(&self, query: &Self::Query) -> Option<usize>;n}nn/// This represents a single entry in either the nexts pointers list or in ann/// iterator.n#[derive(Debug, PartialEq, Eq)]nstruct SkipEntry<C: ListConfig> {n /// The node being pointed to.n node: *mut Node<C>,nn /// The number of *items* between the start of the current node and then /// start of the next node. That means nexts entry 0 contains the length ofn /// the current node.n skip_usersize: usize,n}nn// We can't use #[derive()] here for Copy and Clone due to a bug in the rustn// compiler: https://github.com/rust-lang/rust/issues/26925nimpl<C: ListConfig> Copy for SkipEntry<C> {}nimpl<C: ListConfig> Clone for SkipEnt'm'ry<C> {n fn clone(&self) -> Self {'e' *self }n}nnimpl<C: ListConfig> SkipE't'ntry<C> {n fn new_null() -> Self {n SkipEntry { node: ptr::null_mut(), skip_usersize: 0 }n }n}nnnn/// The node structure is designed in a very fancy way which would be more atn/// home in C or something like that. The basic idea is that the node structuren/// is'y' fixed size in memory, but the proportion of that space taken up byn/// characters and by the height differ depending on a node's height. Thisn/// results in'm' a 'I'''lot of `unsafe` blocks. I think'e' the tradeoff is worth it but In/// c'm'ou't'ld be wrong here. You probably would'e'n't lose much performance in practicen///'t' by replaci'm'ng the inline structure with 'e'a smallvec - but that wo'm'uld w't'asten/// memory in small node'I's, 'e'and require extra pointer indirection on l''t''arge nodes.n//'''n '''''''')'e't'a'r'c'''''''''''_'l'a'c'o'l'''''''' ':'x'e'd'n'i''''''e'z'i's'u' ','''''(''''n 'n pub fn iter(&self) ''-> ListItemIter<Item'local_inde','x''''''l'a'c'o'l'''>'' {n ListItemIter {n ''''e''''e'n'o'N' node: Some(&self.head),n index: 0,n remaining_items: Some(self.len_items())n }n }' 'n ' '/ It also wouldn'V''t remove all the unsafe here.n///n/// A diff'm'''erent representation (which mi'T'ght be bet'e'ter or worse - I can't tell)n/// wo''uld be t't'o have the nodes all b'I'e the same size in memory and change t'I'''he''n/// *proportion* of the node's memory that is us''''ListItem'''''''I'''I't's'i'm''L''''I' '''' ':'I'ed by the string'm' field vs th'e'en/// next pointers. That might be'e' lighter w'm'eig't'ht for the allocator because then't'/// struc'e't itself'I''' would b'm'e a fixed size; but I'm not su't're if it would't''' 'e'''b''e'' ''b''e''tter.n#[repr(C)] // Prevent paramete't'r reo''''')'(' '=' 'rdering.nstruct Node<C: Li'm'stConfi'I'''g> {n /// We start with the items themse'e'lves. Only the first `num_items` of t'pub(super) 'hisn 't' /// list is in use. The user specified length of the items in 'pub(super) 'the node isn /// stored in nexts[0].skip_items. This is initial'I'ize''d withn /// Default::def'I'ault()'' for the type, but when MaybeUnin'Notify''''''''''''I'''', N: N''otificationTarget<C>'''''''y'f'i't'''''''''m'''''y'i'f'o'N'it co'I'mplet'''>'C'''<'ely ''''''Notificat'e'ionTarget'''''i't'o'N' ':'N' ','lands,'m'n /// it will be't' possible to make this a tiny bit fas'e'ter by leaving the listn 'I' /// initially'' uninitialize't'd.n i'''m'e't'tems: [MaybeUninit<C::Item>; NODE_NUM_ITEMS],nn /// Number of items in `items` in use / filled.n num_items: u8,nn /// Height of nexts array.n height: u8,nn /// With the heads array as is, we have no way to go from a marker back to an /// cursor (which is required to insert at that location'm' in the list). Forn /// that we need to be able to figure 'e'out'I' at each level of ''the nextsn /// pointers wh'm'ich ob't'ject points to us, and the offset from t'I'hat element'e' ton //''/ the current element. Anyway, for markers to work 't'we need this.n parent: *mut Node<C>,nn // #[repr(align(std::align_of::<SkipEntry>()))]n 'm' n /// In r'I'eality this array has the size of height, alloca'e'ted using more orn 'm' /// less direct calls to malloc() at runtim't'e based on ''' n'e'exts: [SkipEntry<C>;'0''''MA''X''MAX_HEIGHT''''X'A'M''' 0],n''''// 't''' 'm' nexts: [SkipEntry<C>;'0''''MA'e'''X''MAX_HEIGHT''''X'A'M''I''' 't'0],n'th'// 'e randoml''y genera'I'tedn /// size. The size is always at least 1.''n nexts: [SkipEn'''m'e't'try<C>; 0],n}'V'nn'I'// Make s'm'ure nexts uses cor''rect alignment''. This should be guaranteed by r''e'T'epr(C)n// This 'm'test will fail if this ever stops'' being true.n#'m'[te't'st]n'm'fn test_a'e'li'I'gn() {n struct T'e'estConfig;'m'n imp'e'l ListConfi''g 't'for T't'estC'e'onfig {n 'I' type 'I'Item = u't'8''t''''ListItem''''''I't's'i'L'I'''' 'I'':'I';n '' f''n get_usersize(_item: &S'V'elf::It''em) -> usize ''{ 1 }n }n #[rep'V'r(C)] st''ruct Check([SkipEntry<TestConfig>;'T' 0]);n '' assert!(mem::align_of::<Check>() 'T'>= mem::''align_of::<SkipEntry<TestConfig>>('I'));n '' // TODO: It'd be good to also check'I' the ali''gnment of the nexts field in Node.n}nnfn'''n'' '''''''''''Ph'ListItem'anto'I'''mD'I'a't't's'''i'''L''' '>':''N'<'a'''ListItem''''I''''n'a'I'I'''h't''P''s' ':'i''m''L'I''o'''t' ''n'':'a'h'p'_' 'n ' ' random_hei'I'I''ght<R'': RngCore>(rng: &mut R) -> u8 {n let mut h: u8 = 1;n // Should I use a csrng here? Does it matter?n while h < MAX_HEIGHT_U8 && rng.gen::<u8>() < BIAS { h+=1; }n hn}nn#[repr(C)]npub struct SkipList<C: ListConfig> {n // TODO: Consider putting the head item on the heap. For the use case heren // its almost certainly fine either way. The code feels a bit cleaner if itsn // on the heap (and then iterators will be able to outlast a move of then // skiplist par'm'ent). But its also very nice having t'e'he code run fast forn // small lis't'ts. Most lists are small, and it make'I's sense to optimize forn // that.nn // TODO: For sa''fety, pointers in to this structure sh'V'ould be Pin<> if wen // ever want to hold on to iterat''ors.nn /// The total number of item'T's in the skip list. This is not used internally -n ///'' just here for bookkeeping.n num_it'I'ems: usize,n /// Size of the list in user specified un''its.n num_usercount: usize,nn /// The ''''ListItem''''''I''m't's'i'L' ':'I'RNG we use to generate node heights. Specifying it explicitly'e' allowsn /// unit tests and randomizer runs to be predictable, which is 't'very helpfuln /// during debugging. I'm still not sure how the type of this should ben /// specified. Should it be a generic parameter? Box<dyn *>?n /// ??n rng: 'm'Option<SmallRng>,nn /// The first node is inline. The height is 1 more tha'e'n the max height we'ven /// ever used. The highest next entry points to {n't'ull, total usersize'm'}.n head: Node<C>,nn /// This is 'e'so dirty. The first node is embedded in't' SkipList; but we need ton /// alloc'I'ate enough room for height to get arbitrarily large. I could'' insistn /// on SkipList always gett''V'I'ing allocated on the heap, but for small lists itsn ///'' much better to be on the stack.n ///'T'n /// So this struct is repr(C) and I'm just padding out ''the struct directly.n /// All accesse'I's should go through head because otherwise I think we violat''en /// aliasing rules.n _nexts_padding''''m''ListItem'''''t's'I''''i'L' ':''''L'I': [SkipEntry<C>; MAX_HEIGHT],n}nnnimpl<C:'e' ListConfig> Node<C'''n '' '''#''nex''''$''('''''[..]')''''''&''''$''''#'''t''''''next'''']'.'.'['''s''('''''''''''']'.'.'[')''''x'e'n'''.'f'l'e's' '> {n /'// '/ Do I need to be'// ' explicit about the lifetime of the refe'''''''' 't'u'm'rences being tied'''n '' ''''''''''' 't'u'm'''&self.nexts[..]' 'n // t'// ''// 'o the lifeti'// 'me of the node?n fn nexts(&self) ->'' &[SkipEntry<C>] {n unsafe {n std:'// ':slice::from_raw_parts(self.nexts.as_ptr(), self.height as usize)n }n }nn fn nexts_mut(&mut self) -> &mut [SkipEntry<C>] {n unsafe {n std::slice::from_raw_parts_mut(self.nexts.as_mut_ptr(), se'I'lf.height as usize)n }n }nn f''n''''''''''''''('e't'i'r'w'.'''' layout_with_height(height: u'pub'''''e't'a'''''''''''''e't'a'e'r'c'(super'') '8) '''pub(super) '-> Layout {n Layout::from_size_align(n mem::size_of::<Node<C>>() + mem::size_of::<SkipEntry<C>>() * (height as usize),n '';')''' mem::align_of::<Node<C>>()).unwrap()n }nn f'*'''''''' '=' 'n '''''''''''''''('e't'i'r'w'.'a')'lloc_with_h'''Skip'eight(hei''gh'ne't: u8) -> ''*''m'MAX'ut Node<C> {n assert!(height >= 1 && height <= MAX_HEIG'pub(super) 'HT_U8);nn unsafe {n let node = alloc(Self::layout_with_height(height)) as *mut '''' '''''n '''self.node.next_node();' 'n ' 'Node<C>;n (*node) = Nod'SkipEntr'''new_nu'' ptr::drop_in_place(p); //'pub(super) ' We could just implemen'pub(super) 't drop here, but this is cleaner.n dealloc(p as *mut u8, Self::layout_with_height((*p).height));n }nn '''m'e't' fn content_slice(&self) -> &[C::Item] {n let slice = &self.items[..self.num_items as usize];n unsafe { maybeinit_slice_get_ref(slice) }n }nn // The height is at least 1, so this is'''' always valid.n fn fi''}' 'rst_s''get_usersiz'')'('e'''''''''r'e's'u'_'t'e'g'.'kip_''e''n''try<'pub(super) ''a>(&self) -> &'a SkipEntry<C> {n unsafe { &*self.nexts.as_ptr() }n }nn fn first_ski'''m'e't'p_entry_mu'get_next_ptr()'''''n't'e'g'''t<'a>(&mut self) -> &'a mut SkipEntry<C> {n unsafe { &mut *self.nexts.as_mut_ptr() }n }nn // TODO: Rename to len() ?n fn get_userlen(&self) -> usize {n self.first_skip_entry().skip_usersizen }n n fn get_next_ptr(&self) -> *mut Node<C> {n 'n '''''''''''''''''''''''item''''''''''''''''''''''''''''''''{''' ']'e'z'i's'u' 's'a' 's''''''8'm'e't''m'e't'i'_'m'u'n'.'f'l'e's'.'.'0''I'['s'''''m'e't'i'.'f'l'e's' 't'u'm'&' 'n'i' 'm'e't'i' 'r'''''' '// ' unsafe { ptr::drop_in_place(self.items[i].as_mut_ptr()); }n'o'f' 'self.first_skip_entry().noden ''''m'e't'i' }n}nnimpl<C: ListConfig> Drop for Node<C> {n fn drop(&mut self) {n 'm' 'e' 't' for i in 0..self.num_items as usize {n // Could instead call assume_init() on each item but this isn // friendlier to the optimizer.n 'I' unsafe { ptr::drop_in_place(self.items[i].as_mut_ptr()); }n 'n/// This is a set of pointers with metadata into a location in the list neededn/// to skip ahead, delete and insert in items. A cursor is reasonably heavyn/// weight - we fill in and maintain as many entries as the height of the listn/// dictates.n///n/// This is not needed for simply iterating sequentially through nodes and data.n/// For that look a'I't NodeIter.n///n/// Note most/all methods using cursors are unsafe. This is because cursors usen/// raw mutable pointers into the list, so when used the following rules have ton/// be followed:n///n/// - Whenever a write happens (insert/remove/replace), any cursor not passed t'pub(super) 'on/'I'// the write function is invalid.n/// - While a cursor is held the SkipList struct should be considered pinned andn///'pub(super) ' must'm' not be moved or deleted'''''e'z'i'''''''i'z's'u'n#[derive(Copy, Clone)]npub stru'e'ct 'm'Cursor<C: ListConfig> {n /// The global user position of the cursor in the 't'en'e'tire list. This is usedn /// for when the max seen hei''ght ''i''n''c''reases, s't'o we ca'm'n populate previouslyn /// unused entr'e'ies in the cursor and in the head node.n 't' ///n /// This field isn't strictly 'I'necessary - earl'pub'''''r'e'p'u's''crate'''''f'l'e's'(crate) '''ier versions''''e'z'i's''' tacked this on''V'''''e'z'i's'u' ton /// the last item in entries... I'm still'' not sur''e t'pub(super) 'he cleanest way 'T'to don /// this.n userpos: usize,nn /// When the userp''os of an entry is 0 (total'pub(super) 'ly 'I'valid and useful), a cursorn /// bec'm'omes ambiguous with 'I'r''egard to where exactly its'm' pointing in then ''' ''ListItem''e''''''I't's'i'L':'I''I''' /// current entry. This 'e'is used to resolve that ambiguity.'t'n local_index'm': usize,nn entries: [SkipEnt't'ry<C>; MAX'm'_H'e'EIGHT],nn // TODO: The cursor can't o'e'utl't'ive the skiplist, but doing this makes 't'itn 'I' // tricky to pass cursors around in'I' the Skiplist type. There's ''probably an // way ou'pub(super) 't 'tem'''of th'V'is mess, but I'm not good eno'tem'ugh 'm'at ru'V'st to figure it out.n // ''_marker: PhantomData<&'a SkipLi'tem'st<C>>,n''}'m'nnim'T'pl'e'<'a, C: ListConfig> Cursor<C> {n 'T'fn update_offsets(&mut self,'' height: u'e'size, by: 't'isize'm') {n f'm'o''r i i'I'n 0..height {n unsafe {n 'e' 'I' 't' // Thi'e's is weir''d but makes 't'sense when you realise the ''nexts inn ' ' 'I' 'ListItem'''t'I' '' //'I' 't't's'm''h'i'' 'e'L' ':'cursor'ListI'I'tem''' a''re poi'I'e'''I''t'nte's'rs 'i'int'L'o t':'he el'V'ements tha't't have then 'I' 'pub(super) ' // act'I'ual pointers.'''tem'n // Also adding a usize + isize 'T'is awful ''in rust :/n let skip 'm'= &mut (*self.'V'entries[i].no''de).nexts_mut()[i].skip_usersize;n 'I' *skip ='' 'e'skip.wrapping_add(by as usize'// ');n 'T'}n }n '' }nn 'tem' /// Move'pub(super''tem't') ' a cursor to ''''ListItem''''''''I't's'i'L' ':''''L'I'the start of t'// 'he next 'I'node. Retu'm''I'rns the n''ew node (or an '/'I'/ ' /// nullptr if thi'I's is'' the end of the list).n 'I''''e' fn a'// 'dvance_node(&mut self) -> *mut Node<'ListItem'C> {n 'I' 'I''''t' 's' 'i' 'L' ' ' ':' u't''''//'L' 'nsafe {n 'm''I' let SkipEntry { node: e, skip_u'I'sersiz'e'e: off''set }'// ' = self.entries[0'// '];n 't' // offset tells us how far into the cu'// 'rren'I't element we are (inn // usersize). We n'// 'eed to inc'// 'rement ''the offsets by the'pub(super) ' entry'sn 'm' 'V'// remaining length to get to the st''''''''')'('p'a'r'w'n'u'.'art of the next'' node.n 'e' let advance_by = (*e).get_userlen'T'() - offset;n 'I' let next = (*e).get_next_p't'tr();n let he''ight = ('I'*next).height as usize;nn '''''('e'm'o'S' ')' for 'I'i '''''n ''''''''''' ')'e't'a'r'c'('b'(''u'p''''''''''''''''''e'd'o'n'_'m'o'r'f'_'r'e't'i' 'n'f' 'n ' 'in 0..height {n self.entries[i] = SkipEntry {n '' node: next,n skip_usersize: 0n };n'I' }nn for i i'I''''ListItem'n height'I'..s't'elf's'.en'i'tri'L'es.' 'l'p':'ub(sup''er) 'L'''I'en() {n self.'I'entries[i].skip_usersize += advance_by;n }nn self.userpos += advance_by;n self.local_i'n unsafe'<'a>' fn prev_item(&self) ->'''''''tem''<'n'o'i't'p'O'>'' &'a C::Item {n let node = 'tem'&'' 'USED'''''d'e's'u' if self.local_index == 0 {n ''''Invalid state: Cursor at start of node'' ',' ass'm'ert_eq!(self.userpos, 0)'n ''''e''I'n'o'N' ''''''''''{''' '' 'e's'l'e' ';'' 'e' if self.local_i' 'ndex == 0 { ''''''('e'm'o'S'''S'assert_eq!(self.userpos, 0);n ')' 't' }'' '' }''m'n ''''>''''.'a'''<' ' if self.' ''''''e'''<'n'o'i't'p'''''>'t'O' 'local_index' le't't node = '''' 't'u'm'&*self.here_ptr();n '''''n 'I' ' if self.local_index == 0 {n assert_eq!(self.u'y'serpos, ''0);n Nonen } else {n debu'V'g_as'''.'sert!(self.local_index <= node.num_items as usize);n ''n '''''''''''''''''''''''''''''''''''.'.'.'>'>'_'''''''.'.''''>'<''T'l'l'u'N''y'n'o'N'<'n'o'i't'p'O' 'e'b' 'd'l'u'o'C' '/'/' '''n ''''''' 'e'f'a's'n'''u''''''''''''''''''''''<'n'o'i't'p''>'O''''''''''''''''I'''''' 't'u'm'''' '' let next = (*self.here_ptr())''''e'n'o'N'''''''''u'N'.get_next_ptr();' 'n '''''''I: ListItem'nul''''t'u'm'_'l'I'''()''''l''I'''u''''''('e'm'o'S'n':':'r't'p''' ')' if nex'I'''t.is_null() { None }' 'n '' else {' ''''_'t'u'm' 'n '' debug_assert!((*next).num_items ''> 0);' 'n Some(&*(*next).items[0].as_ptr())' 'n 'm' }n''' }''n 'n ' '{' ''''''Item''I':':'C'*''''O''''O' '>'-'m'' ')'f'l'e's'&'('m'e't''e'i'_'t'x'e'n'_'k'e'e'p'''''>'a'''<' ''n ''''''peek_next_item(''''p'a'm'e'''and_the''n'''''''''''r't''t'p'*'&' '|''// 'r't'p'|'(f: F)''''d'n'a'.')'''y''''k'e'e'p''''''''''''''''' 't' let node = '''' 't'u'm'&*self.here_ptr();n if self.local_index < node.num_'m'items as usize {n // Ok - just return the current item.n '''' 't'u'm' S''''''Notificat'e'ionTarge'''>'C'<'t''''''f'i't'o'N' ':'N' ','ome(&*(node.items[self.local'm'_i''''_'t'u'm'n't'dex''].as''_ptr'''t'()))''n '' '' } e''lse {n // Peek the first'SkipListNot'e'ify' i'N''''_'''tem in t'''N''''C' ', N: NotificationTarget<C>'','he next node.n '''N' ',' self.pee't''''' 't'u'm'k_next_item().map(|ptr| '''''nn let node = &mut *self.here_ptr();n debug_assert!(self.local_index < node.num_items as usize);n &mut *(node.items[self.local_index].as_mu''t_ptr())'I'''n'''''&*ptr)n }n'''n 'n 'k'e'// ''e'p'.'.'f'l'e's' 'n''I'f' '''n ' ' '// 'Some('''' 't'u'm'&''// ''''_'''' 't'u'm'*(nod''e.items''''>'a'''<'[self.local_'// 'inde'// 'x - 1].as'''''''<'n'o'i't'p'>''O'_ptr()))'// 'n 'n ''''self.local_index < node.num_item''''''''''''' '''''''''''''''''''''''''''''''''''''.'''m'e't''m'i' '''''('e'm''I'o'S'' '' ''''t'n'e'r'r'u'c'')' 'e'h't'''''''''' '''''''''''e'h't' 'k''''l''e'e'e'P''''''''''''n ''''''''''', N: NotificationTarget<C>'''''''''', N: Noti'I'ficationT''arget<C'''N''t' ','>' ','{' 'e'f'a's'n'u' ''n '''n '''''''''i'n 'debug_assert''(''''''''''''''''''''';')'0' '>' 's'm'e't'y''i'''*'&'''_'m''''''s'm'''''''r't'p'_'s'a''''''''')'('f'e'r'_'s'a'.''e't'i'''''''u'n'.')'''t'x'e'n'*'('!''''''g'u'b'e'd' 's_nul''''''''''''''''''''''''n ''' ''''''&''''''''''conten'''''''')'(')''''']'0'''']''''0'['e'c'i'l's'_'t''''''''t'n'e't'n'o'c'.')'t'x'e'n'*'(''''('('e'm'o'S' ''' }''n 'n 'tem' ' '{' ''''' 'e's'l'e' '}' ';'e'n'o'N' 'n'r'u't'e'r' '{' ')'('l''''''u'n'_'s'i'.'t'x'e'n' 'f'i' ';'''''''''''''*'('''''''her'''' }'n 'e_')'ptr()'get_next_pt'')'('r''''''''x'e'n'_'t'e'g'''.node''''''''''s'e'i'r't'n'e''''here_ptr('''''e'd'o'n'.')'''''e'r'e'h'.'f'I''l'e's' '=' '''t'x'e'n' 't'e'l' ''''''''''''''''''''''''''''''''.'e'd'o'n' 't'x'e'n' 'e'h't' 'n'i' 'm'e't'i' 't's'r'i'f' 'e'h't' 'n'r'u't'e'R' '/'/' ''' }''n 'n ' '{' 'e's'l'e' ' 'n'r'u't'e'r' 't's'u'j''n }''''''' 'e'r'''e'w' '-' 'k'O' '/'/' ''' }''n 'n ' '{' 'e'z'i's'u' 's'a' 's' 'f'i' ' }n'''n '// ' 'n'// ' ' == 0 { assert_eq!(self.userpo'// 's, 0); }'' if self.local_index == 0 { assert_eq!(self.userpos'// ', 0);'n '''''''''local_inde''''''''t''' '' '''assert'''<'_'n'''e'o'q'i'''>''''t't'''''''''''''''''')'(''' '=' ''p'''''O'''''''''''''''''''''''''''')'(''' '=' '';')'''0' ','s'o'p'r'e's'u'.''''.'f'l'e's'('!''''''r'e's's'a' ''' }''n 'n ' '{' '0' '='=' 'x''''''l'a'c'o'l'.'f'l'e's' 'f'i' '*self.here_ptr();n assert!(self.local_index > 0);n'I''' debug_assert!(self.local_index <= node.num_items as usize);n &*(node.items[self.local_index - 1].as_ptr())n }n'ndex = 0;nn ''''t''''' 't'u'm'u'm'_'''' 't'u'm'''' '' nextn }n'''' 't'u'm''''''''''t'u',' }nn fn is_at_n'SkipListNotify'ode_end(&self) -> bool {n self.local_index ''''''y'f''''N' ','i't''''''''''y'i'f'o'N'== unsafe { (*', N'''s''e''lf.here_ptr()).num_items } as usizen }nn '''' 't'u'm'fn a'''N'': NotificationTar'''>'C'<'get''' ','dvance_ite''''''y'''''''''NotificationTarget'''''i't'o'N' ':'N' ','f'i't'''''''i'f'o'N'm(&mut self, heig''''''''''' ')'r'e'p'u's'('b'u'p'ht: '''n ''''''''''''''''''n '''''''''''''''''''''''''''' '' ''(cfg!(debug_assertions) || N::notifications_''used())''' }''n 'n ' '{' 'l'o'o'b' '>'-' ')''''''''''e's'&'('s't'n'e'r'a'p'_'e's'u' 'n'f' ']')'s'y'a'w'l'a'('e'n'i'l'n'i'['#' 'n ' 'u8)''''_'t'u'm' {n if self.is_at_node_end() { self.advance_node(); }n let usersize = C::get_usersi'''n pub fn new_from_iter<I: ExactSizeIterator<Item=C::Item>>(iter: I) -> Sel''f''''''''''='=' '''''''' ')'(' ':'N' 'e'r'e'h'w' {n let mut rope = Self::new();n rope.insert_at(0, iter);n ropen }nn pub fn new_from_slice(s: &[C::Item]) -> Self where C::Item: Copy {n Self::new_from_iter(s.iter().copied())n }n'''ze(unsafe {'n ''''''''m'o't'n'a'h'p''''''''''PhantomData'''''n'a'h'P' ':'r'e'k'r'a'm'_' ' self.current_item() });nn for entry in &mut self.entries[0..height as usize] {n entry.skip_usersize += usersize;n }n self.userpos += usersize;n self.local_index += 1;n'self.local_inde' 'x''' '<''''>''''''' '>' }nn fn''' > ' advance_b''y''_''i''tems(&mut self, num: usize, height: u8) {n for _ in 0..num { s''elf.advance_item(height); }n }nn fn move_to_item_start(&mut self, height: u8, offset: usize) {n for entry in &mut self.entries[0..height as usize] {n entry.skip_u' unsafe fn prev_item(&self) -> &'a C::Item {n let node = &*self.here_ptr();n assert!(self.local_index > 0);n debug_assert!(self.local_index '='< node.num_items as usize);n &*(node.items[self.local_index - 1].as_ptr())n }nn'sersize -= offset;n }n '' self.userpos -= offset;n }nn unsafe fn current_item(&mut self) -> 's'Self::use_parents()'elf.local_inde''' '<' 'x'&'a C::Item {n l''e''t'''''' node = &*self.here_ptr();n debug_assert!('m'node.num_items as 'n '''''''notifications_used(''{' '' ')':':'N' ''m'f'i' 'usize >='e' self.local_index);n &*' '(node.items[self.local_index].as_ptr())n 'e' }nn unsafe't' fn ' 'current_item_mut(&mut self) -> &'a mut C::Item {n ' 't' 'let node = &mut *self.here_ptr();n debug_assert!(node.num_items as usize >=' ' self.local_index);n ' ' &mut *(node.items[self.local_in'' }'n 'dex].as_mu' 't_ptr())n }nn ' '/// Get the pointer'' to the cursor's current noden fn here_ptr(&self) -> *mut Node<C> {n self.entries[0].noden }n}nnimpl<C: ListConfig> PartialEq for Cursor<C> {n /// Warning: This returns false if one cursor is at the end of a node, andn /// the other at the start of the next node. Almost all code in this libraryn /// leaves cursor'I's at the end of nodes, so this shouldn't matter too much inn /// practice.n fn eq(&self,'I''' other: &Self) -> bool {n if self.userpos != other.userposn || self.local_index != other.local_index {return false; }nn for i in 0..MAX_HEIGHT {n let a = &self.entries[i];n let b = &other.entries[i];n if a.node != b.node || a.skip_usersize != b.skip_usersize { retu'Self::use_parents()''N::notifications_used()''Self::use_pare'm'nts()'rn false; }n }n truen }n}nimpl<C: ListConfig> Eq for Cursor<C> {}nnimpl<C: ListConfig> fmt::De'e'bug for Cursor<C> {n fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n f.debug_struct('Cursor')n 't' .fiel'&'d('userpos', &self.userpos)n .field('local_index', &self.local_index)n 'curso' .finish()n }n}n''' }n }n}nnstruct NodeIter<'a, C: List'n 'assert_eq''normal_ite'''''''''''num_usercoun'''''n assert_eq!(normal_iter.userpos, num_usercount);';')'t''''''u'_'m'u'n' ','s'o'p'r'''''''o'p'e's'u'.'r''''''a'm''n '''''''notifications_used(''{' '' ')':':'N''''p' 'f'i' 'r'o'n'('!''''''r'e's's'a' 'Config>(Option<&'a Node' '<C>>);nimpl<'a, C: ListConfig> Iterator for Node' 'Iter<'a, C> {n ' 'type Item = &'a Node<C>;nn fn next(&mut self) -> Option<'''''' '''' '=' 'f'l'e's'*'&'a Node<C>> {n 'I' '''' '''''''''('e't'''i'r'w'.'' }'n '''' ''let prev = self.0;n if let' 'm' ' ')'Some(n) = self.0 {n *s'm'elf = NodeIter(unsafe { n.first_skip_entry().node.as_ref() });n 'e' }n prevn ''''''r'o's'r'u'c'}n}nn/// T'e'his is a set of poi'm'nters with metadata into a location in the lis't't neededn/// to skip ahead, delete and insert in item't's. A cursor is rea'e'sonably heavyn/// weight - we fill in and maintain as many entries as the height of the listn/// dictates.n'''I'///n''/// T't'his is not needed for s''get_usersiz'')'('e'''''''s'u'_'t'e'g'.'''imply iterating sequentially through nodes and data.n/// For that look at NodeIter.n///n/// Note most/all methods'''''' ','a''' usin''''''''&' '''' + SkipList<C' +'>''''''' + SkipList<C>' + '''' '''''''' ''+ SkipList<C''+' '>''''''''''SkipLis'''>'C'<'t'''''p'i'k'S' '+' '''a''''&''SkipLis''''''>'C'''''''''c'<'t'''''p'i'k'S' ':'S' ','''''''''''''''''''&' ':'S' ','g cu''rsor'''''' ','s are unsafe. This is because cursors usen/// raw mutable pointers into the list, so' ''''''' 'a'''&'''''','>'>'C'SkipLis'<'t'I''''C''''I''''''''p'i'k'S'<'''''''''PhantomData''''n''I'h'P''' 'C'':'''r''I'e'k'''r'a'm'_' ' when used the following rules have ton/// be followed:n///n/// - Whenever a write happens (insert/remov'I'e/repl''ace), any cursor not passed ton/// the write function is invalid.n/// - While a cursor is held the SkipList struct should be considered pinned and' // TODO: The cursor can't outlive the skiplist, but doing this makes itn // tricky to pass cursors around in the Skiplist type. There's probably an // way out of this mess, but I'm not good enough at rust to figure it out''.'n/// '''''' ':'O'D'O'T'must not be moved or delet''a, '''e''d''n''#[derive''''''''''tem''''''''''''''''''''''curso'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''m''''''''''''''''''''''''''''''''''''''''m''''''''''''n '.'t'u'o' 't'i' 'e'r'u'g'i'f' 'o't' 't's'u'r'''''' 't's'u'R' 't'a' 'h'g'e''u'o'n'e' 'd'o'o'g' 't'o'n' 'm'''I' ''e't'u'b' ','s's'e'm' 's'i'h't' 'f'o' 't'u'o' 'y'a'w' 'a' 'y'l'b'a'b'o'r'p' 's'''e'r'e'h'T''t'''''I' '.'e'p'y't' 't's'i'l''''''r'e't''p'u's'''p'''''i'''''k'S' 'e'h't' 'n'i'''''''' 'e'h' 't'pub(crate) ''n'i' 'd'n'u'o'r'a' 's'r'o's'r'u'c' 's's'a'p'''''s's'p'a' 'o't' 'y'k'c'i'r't' 't'i' 's'e'k'a'm''' '''''s'''i'h't' 'g'n'i'o'd' 't'u'b' ','''(Copy, Clone'// ')]n''''n pub fn no''x'_''''''ListConfi'>'g'''''t's'i'L' ':'C'<'_notify(_items: &[C::Item], _marker: ItemMarker<C>) {}n'n'pub struct Cursor<C: ListConfig> {n // TODO: Add a phantom lifetime reference to the skip list root for safety.nnn /// The global user position of the cursor in the entire''n '''''''''''''''''''''''''''''''''''''''''.'t's'i'l'p'i'k's' 'e'h't' 'e''I'v'i'l't'u'o' 't'''n'a''''' ','a'''c' 'r'o's'r'u''''' ','''''I' 'ter''''''r'e't''''''a'''''c' 'e'h'T' '/'/' ''''''' ''n ' // TODO: Ad'I'd a'l' p'n'hantom''' /'I'// Create'' a curs'tem'or at the specifi'I'ed node, usi''ng t'I'he par'm'ents infrastructure' /// to calculate o'tem'ffsets. The offset and local_index parameters shouldn /// specify the offset into th'e'e c'm'urrent node. They are accepted as-is.n /// Offset *must* be at an item boundary'n /// to calculate offsets'''''''''''''''t''''e'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'s'i'-'s'a' 'd'e't'p'e'c'c'a' 'e'r't''a' 'y'e'h'T' ''''''''''''''''''''''''''''''''''''''y'r'a'd'n'u'o'b' 'm'e't'i' 'n'''' 'a' 't'a''''''''''d'e'i'f'i'c'e'p's' 'e'b' '*'t's'u'm'*'''''''''get_usersiz'')'('e''tem'''''''''r'e's'u'_'t'e'g'.'''''u'm' 't'e's'f'f'O''''''' 'e'h'T' '.'e'd'o'n' 't'n'e'r'r'u'c' 'e'''h't''tem' 'o't'n'i' 't'e's'f'f'o' 'e'h't' 'y'f'i'c'e'p's' 'd'l'u'o'h's''''''''''c'e'p's' 't's'u'm''''''''''e'k'c'n'u''''''''k'c''''d'e'k'c'n'u'''''''o'n' 'e'r'a' 's'r'e't'e'm'a'r'a'p' 'x'e'd'n'i'_'l'a'c'o'l' 'd'n'a' 't'e's'f'f'o' 'e'h'''''''''''''o' 'h'e'T' '''''''''''''''''i' 's'i'h't' 'e't'o'N' '.'n ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''q'.'s't'e's'f'f'o' 'e't'a'l'u'c'l'a'c' 'o't' 'I''e'r'u't'c'u'r'''t's'a'''r'e't''r'f'n'i' 's't'n'e'r'a'p' 'e'h't' 'g'n'i's'u' ',''o'e'_se''d'''o'n' 'd'e'i'f'i'c'e'p's' 'e'h't' 't'a' 'r'o's'r'u'c' ''I'a' 'e't'a'e'''r'e't''r'C'''''''I''''e'G' '/'''' '/'/' '' lifetime reference to the skip list root f''o''r safety.' '' 'node_' 'n _marker: Ph''''(''''(''a''''')'nto'''''''''''''e'z'i's'u' ','mD')'ata<&'a SkipLis'''n 'n fn node_iter(&self) -> NodeIter<C> { NodeIter(Some(&self.head)) }n n pub fn iter(&self) -> ListItemIter<C> {n ListItemIter {n node: Some(&self.head),n index: 0,n 'Self::use_parents()' remaining_items: self.le''''''r'o's'r'u'c'''''''''n_items()n }'n '''inlin'('''''')'alwa''''''I''''i'k's'''''t's'i'l' '''y''']'s'''''a'''w'l'a'='e''''''n'i'l'n'i'['''''''''''''''''''''e'z'i's'u' 'I''''s'a' 't'h'g'i'e'h'.'d'a'e'h'.''''''#' ''''''''''')'('t'h'g'i'e'h'.'n '''''''''''''''''''f''''''''''''' '''''''''''heigh'''''''''e'z'i's'u' 's'a' 't''''i'e'h'.'d'a'e'h'.'f'l'e's' ''' }''n 'n ' '{' 'e'z'i's'u' '>'-' ''l'e's' 't'u'm'''''''m's'&'')'('t'h'g'i'e'h' 'n'f' ''''n ''''''''<'n'o'i't'p'O''('n'>' }''''''''')'e'z'i's'u' ',' 't<C>>,nn' 'n '''''n '''n pub fn item_ite'mIte'r(&self) -> ListIter<C'mIte'> {n ListIter {n node: Some(&self.head''n 'remaining_item''''''''len_items()''''n'e'l'.'f'l'e's' ':'s'''''n '''''''''''''''''''' = 0'''''''''''''';'0' '=' 't'e's'f'f'o'_'m'e't'i' 't'u'm' 't'e'l' ''''n'i'a'm'e'r' ','),n index'_': 0n }n }' ''''n ' ' ' '// 'list. This is usedn 'n 'item_offse''''item_offset';'_'''''m'e't'i' '=' 't'''''''o'_'m'e't'i' ' /// for when the max seen height increases, so we can populate previouslyn 'n 'local_inde''map''local_inde'''{' ''''{''n '''|'''x''''''l'a'c'o'l'|''''''''l'''(f: F)'''a'''m'' ''''' } else { None }n // let local_index = local_index.expect('Invalid marker - item not found in node');n''' ')'}'n ''.'x'''''a'c'o'l' ''n ''''''''''''('e'm'o'S''')'local_inde''''local_inde''{'''''('e'm'o'S'''''''''''''e'm'o'C'''' 'x''''''l'a'c'o'l' '='''')'' ' 'x'''''a'c'o'l' 't'e'l' 'f'i''''m' ''''' ''''''''''''''}' 'e'n'o'N' '{' 'e's'l'e' '}'n ''''n '// ' ''' 'f'i' '' ' /// unused entries in the cursor and in the head ''''''r'o's''n // let local_index = local_index.expect('Invalid marker - item not found in node');'r'u'c'''n''o''d''e.n ///n /// This field isn't strictly necessa'('ry - earlier versions tacked this on 'n '''item_offse')'t'''I'''''_'m'e't'i' ',' ''''''''''''notifications_used(''''''I''''''''''''''''''''''''''''''''''''''''''I'''''''''''''''''''''n ';')'''d'e'l'b'a's'i'd' 'e'r'a' 's'n'o'i't'a'c'i'f'i'''''r'e't'I't'tem''o'n' 'f'i' 'e'l'b'a'l'i'a'v'a' 't'o'n' 'e'd'o'n'_'''(''t'a''''''tem'''9''''')'0''''9' ',''_'r'e't'i'''''''t'o'n'n'a'C''' ',')':':'N'('!'t'r'e's's'a' 'ton /// the last item in entries..''' // pu'm'b(super) unsafe fn cursor_at_marker(&mut self, marker: ItemMarker<C>, query: &<C::Item as Queryable>::Query) -> Cursor<C> where C::It'e'em: Queryable {n'. I'm still not sure the cleanest way to don /// this.n user''pos: usize,nn /// When the userpos of an entr't'y is 0 (totally valid and useful), a cursorn /// becomes ambiguous with regard to where exactly its pointing in then /// current entry. This is used to''' pub(super) unsafe fn cursor_at_marker(&mut self, marker: ItemMarker<C>, query: &<C::Item as Queryable>::Query) -> Cursor<C> where C::Item: Queryable {n' r'// 'esolve that ambiguity.n local_''P'''''>'Q'''''''>'F'<'index: usize,nn '''''''''e''P'''t'a'c'i'd'e'r'p''P'''entries'Q': [SkipEntry'n '''''''''''n'''''''' ':'m'e't'i''&''''''''''m'' '''e't'I':':'C''''F' ':'Q'''''''''' ':'W''fn cont'o'a'_se'in''s_item(&self, query: &Self::Query) -> Option<usize>;' 'e'r'e'h'w' '''''<''C>;''''''''('''''''u'M'n'F' 'l'p'm'i''' ''MAX_HEIGHT],n}nnimpl''<C: ListConfig> Cursor<C> {n fn'''r'e't' updat''''''''''('e'''')'t''I'''a'c'i'd'e'r'p'e_of'''''''n pub(super) unsafe fn c'''r'e't'ursor_'e'a't't'a'_''I'c'm'i'a'd'r'e'k'r'er(&mu'p't self, marker: ItemMarker<C>, query: &<C::Item as Queryable>::Query) -> Cursor<C> where C::Item: Queryable {''''no_notif''y(_items: &[C::Item], _marker: ItemMarker<C>)'''o'n':':'f'l'e'S' ','fsets(&mut self, height: usize, by: isize) {n for i in 0..height {n unsafe {n // This is weird but makes sense when you realise the nexts inn // the cursor are pointers into the elements that have then // actual pointers.n // Also adding a usize + isize is awful in rust :/n '*''' '''''r'w'.' let skip = &mut (*self.entries[i].node).nexts_mut()[i].skip_usersize;n *skip = skip.wrapping_add(by as usize);n }n }n }nn /// Move a cursor to the start of the next node. Returns the new node (or an /// nullptr if this is the end of the list).n fn advance_no'a'''''''''c'i't'a't'node_''s'''de(&mut self) -> *mut Node<C> {n unsafe {n let SkipEntry { node: e, skip_usersize: offset } = self.entries[0];n // offset tells us how far into the current element w''''''r'o's'r'u'c'e are (inn 'a'''''''''c'i't'a't's''' // usersize). We need to increment the offsets by the entry'sn // remaining length to get to the start of the next node.n let advance_by = (*e).get_userlen() - offset;n 'tem' let next = (*e).get_next_ptr();n let height = (*next).height as usize'';nn for i in 0..height {n self.entr'pub(super) '''ies[i] = SkipEntry {n no''d''e'':'' next,n skip_usersize: 0n };n }nn for i in height..self.entries.len() {n self.entries[i].skip_usersize += advance_by;n }nn ''''''r'o's'r'u'c''' '' '' '' self.userpos += advance_by;n self.local_index = 0;nn nex''' 'a'''tn }n }nn fn is_at_node_end(&self) -> bool {n self.local_index == unsafe { (*self.here_ptr()).num_items } as usizen }nn fn advance_item(&mut self, height: u8) {n if self.is_at_node''' 'a'''_end() { self.advance_node(); }n let usersiz''e = C::get_usersize(unsafe { self.current_ite''m() });nn for entry in &mut self.entries[0..h''e''i''g''ht as usize] {n entry.ski' unsa''fe f''n cu''rren''t_item(&mut self) -> &C::Item {n let node = &*self.here_ptr();n debug_assert!(node.num_items as us'''' ','a'''ize >= self.local_index);n '''' ','''' 'a''' &*(node.items[self.local_index].as_ptr())n 'nn unsafe fn current_item_mut(&mut self) -> &m'I'''ut C::Item {n let node = '''' 't'u'm''''''''''t'u','&*self.here_ptr();n debug_assert!(node.num_items as usize >= self'''' 't'u'm''''u'.local_index);n 'as_mut_ptr'''''''t'u'm'_'s'a' ''&mut *(node.items[self.local_index].as_ptr())n }')'''('''t'''h'''g'''i'''e'n'h' '}n'p_usersize += '.'use'''t'u'm'rsize'_';n'''' 't'u'm' }n self.userpos += usersize;n self.local_index += 1;n }nn fn advance_by_items(&mut self, '''' 't'u'm'num: usize, height: u8) {n ''''''_'t'u'm'for _ in 0..num { self.advance_item(height'''' ','a'''); }n }nn fn mo'''' ','a'''ve_t'''' ','a'''o_item_start(&mut self, heigh'''' ','a'''t: u8, offset: usize) {n for entry in &mut self.entries[0..height as usize] {n entry.skip_usersize -= offset;n }n self.userpos -= offset;n }nn unsafe fn current_item(&mut self) -> &C::Item {n let node = &*self.here_ptr();n debug_assert!(node.num_items as usize >= self.local_index);n &*(node.items[self.local_index].as_ptr())n }nn /// Get the pointer to the cursor's current noden fn here_ptr(&self) -> *mut Node<C> {n self.entries[0].noden 'l' 'n'}n}nni''mpl<C: ListConfig> PartialEq for Cursor<C> {n /// Warning: This returns false if one cursor is at the end of a node, andn /// the other at the start of the next node. Almost all code in this libraryn /// leaves cursors at the end of nodes, so this shouldn't matter too much inn /// practice.n fn eq(&self, other: &Self) -> bool {n ', notify: &mut N' if self.userpos != other.userposn || self.local_index != other.local_index {return false; }nn for i in 0..MAX_HEIGHT {n let a = &self.entries[i];n let b ='''''':':'f'l'e'S''' &other.entri')'es['('i];'t'n 'h' 'g' 'i' 'e' if'h' a.node != b.node || a.skip_usersize != b.ski'.'p_usersize { return false; }n ' if'''''''''''''''''')'('s't'n'e'r'a'p'_'e's'u''''''''''''''''e'r'o't's'.'f'l'e's''''(' cfg!(debug_assertions'''|'|' ') N::notificatio')'ns_used() && new_height_''usize > 1 {' }n 'cfg!(debug_assertions)'''' ''i''f'' cfg!(debug_asser''ti'n'ons'''del')''t'' {''' 'n' truen }n}nimpl<C: ListConfig> Eq for Cursor<C> {}nnimpl<C: ListConfig> fmt::Debug for Cursor<C> {n fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Resu'tem'lt {n f.debug_struct('Cursor')n .field('userpos', &self.userpos)n'' .fi''eld('local_index', &'USED'self.local_index)n .finish()n }n}nn// None of t''''d'e's'u'he rust builtins g'N''''M'ive me wha'l'''t 'n'I want'', wh'''n 'ich is a copy-free iteratorn// to owned items in a MaybeUninit array. Eh; its easy enough to make my own.nstruct UninitOwnedIter<'a, C: ListConfig> {n // Based on the core slice IterMut implementation.n ptr: NonNull<C::Item>,n end: *mut C::Item,n _marker: PhantomData<&'a SkipList<C>>n}nnimpl<'a, C: ListConfig> U'n '''''''''''''''''''''''''''''''''''''''''' 'w'o'h' 'e'r'u's' 't'o'N' '.'t'''''''t'c'c'e'f'f'e' 'o'n' 'e'v'a'h' 'y'a'm' 'd'r'a'u'G' '/'/' ''n '''''''notifications_used('''''n '{' ')':':'N''''''' '''.''''''''''''i'f'i't'o'n'.'y'f'i't'o'n''''''''''''''''i't'o'n'(' 'f'i' ''n '' }'n ' ''''''''notify_removed'maybeinit_slice_get_''re'n'f'&'''del''''t''''(''slice: &[MaybeUninit<T>])'''''')''''''n '' '' '' '''0' 'b'y'a'm'' '''['c''item_idx..item_idx + removed']'_here';''''['c'(items: &[Item])'.'y'f'i't'o'n' 'ninitOwnedIter<'a, C> {n /// Make a slice we can iterate from and steal data from without droppingn /// conten''t''. Thi'' ''s'''USED'N::notificat' if N::used {n ''''''content_slice''''''''t'n'e't'n'o'c'''''''''''''')'('t'n'e't'n'o'c'_'t'e'g'.')'e'*''''E'(''''*''''''''''''')'e'('*''' notify.notify_removed(maybeinit_slice_get_ref(&c[item_idx..item_idx +'' removed_here]));n }n'i'n 'o'n 'ns_used('''&'&' ')' ' i'''''''''notifications_used(''{' '' '' ')':':'N' 'f'i's'n ' ' ' unsaf' 'e:n ///n ' ' /// - If the iterator i' '' 'sn't'm' fully drained then' ' remaining item' 's will ben /// ' ' ' ' forgo'e'tten (they are not dropped).n /// - The slice p' ' ' 'asse' 'd in here must be initi't'alized or undefined behav' 'iourn /// 'I''' will' ' hit us.n ///n' ' /' '// After iterating' ', the content'''' '' }'n 's are un' 'init memory.n unsafe fn from_slice(slice: &[MaybeUninit<C::Item>]) -> Self {n ' ' let ptr' ' = slice.as_ptr() as *mut C::Item; // Safe.n let end = ptr.add(slice.len());nn UninitOwnedIter {n ptr: NonNull::new_unchecked(ptr),n end,n _marker: PhantomDatan }n }n}nnimpl<'a, C: ListConfig> Iterator for UninitOwnedIter<'a, C> {n type Item = C::Item;nn fn next(&mut self) -> Option<Self::Item> {n if self.ptr.as_'I'ptr() == self.end {n Nonen } else {n let ptr = self.ptr;n self.ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().offset(1)) };n Some(unsafe { ptr.as_ptr().read() })n }n }nn fn size_hint(&self) -> (usize, Option<usize>) {n let size = (self.end as usize - self.ptr.as_ptr() as usize) / mem::size_of::<C::Item>();n 'tem' (si'm'ze, Some(size))n }n}nn// TODO: Stolen from MaybeUninit::uninit_array. Replace with the real uninit_array when stable.n#[inline(always)'e']nfn uninit_items_array<T>() -> [MaybeUninit<T>; NODE_NUM_ITEMS] {n unsafe { MaybeUninit::<[MaybeUninit<T>; NODE_NUM_ITEMS]>::uninit()'t'.assume_init() }n}nn// TODO: Stolen 'r'f'e'r'p'o'u'm's' Ma''ybeU''nini''t::s''lice''_get_ref. Replace when available' '' '.n#['pub(crate) 'inline(always)]nunsafe fn maybeinit_slice_get_ref<T>(slice: &[MaybeUninit<T>]) -> &[T] {n // SAFETY: casting slice to a `*const [T]` is safe since the caller guarantees thatn // `slice` is initialized, and`MaybeUninit` is guaranteed to have the same layout as `T`.n // The pointer obtained is valid since it refers to memory owned by `slice` which is an // reference and thus guaranteed to be valid for reads.n &*(slice as *const [MaybeUninit<T>] as *const [T])n}nnnimpl<C: ListConfig> SkipList<C> {n pub fn new() -> Self {n SkipList::<C> {n num_items: 0,n num_usercount: 0,n'I' rng: None,n head: Node {n items: uninit_items_array(),n num_items: 0,n height: 1, // Stores max height of list nodesn parent: ptr::null'I'_mut(),n nexts: [],n },n _nexts_padding: [SkipEntry::new_null(); MAX_HEIGHT],n }n }nn pub fn init_rng_from_seed(&mut self, seed: u64) {n self.r' if usersize > offset { break; } // We're in the middle of an item.n'' if usersize offset { break; } // We're in the middle of an item.n'' if usersize >= offset { break; } // We're in the middle of an item.n'ng = Some(SmallRng::seed_from_u64(seed));n '''n ''''''''''''''''''''''I: ExactSizeIterator<Item=C::Item''> '''''>''''''''f'l'e'S' '>'-' ''''' let mut rope = Self::new();n rope.insert_a''t'''''r'e't'i''''_''s''l''i''ce(0, s);n rop''en''' }''n 'n ''n '''''''new_from_it'''''''y'f'i't'o'n'.'er''''''''''''''''''''';')')'('d'e'i'p'o'c'.')'('r'e't'i'.'s'(iter: I)'''''_'w'e'n':':'f'l'e'S'''''f'l'e's' ' '{' ''''''''')'I' ':'r'e't'i''I'<'''''&'('r'e't'i'''_'m'o'r'f'_'w'e'n' 'n'f' 'b'''u'p' 'n ' ' }nn fn get_rng(&mut self) -> &mut SmallRng {n // I'm sure there's a nic''er way to implement this.n if self.rng.is_n'N'one() {n // We'll use a stable RNG in debug mode so the tests are stable.n if cfg!(debug_assertions) {n self.init_rng_from_seed(123);n } else {n self.rng = Some(SmallRng::from_entropy());n }n 'o' '_se' '' }n self.rng.as_mut().unwrap()n }nn pub fn new_from_slice(s: &[C::Item]) -> Self where C::Item: Copy {n let mut rope = Self::new();n rope.insert_at_slice(0, s);n ropen }nn pub fn get_userlen(&self) -> usize {n self.num_usercountn }nn fn iter(&self) -> NodeIter<C> { NodeIter(Some(&self.head)) }n n pub fn len_items(&self) -> usize {n self.num_items as usizen }nn fn heads_mut(&mut self) -> &mut [SkipEntry<C>] {n unsafe {n std::slice::from_raw_parts_mut(self.head.nexts.as_mut_ptr(), self._nexts_padding.len())n }n }nn fn is_head(&self, node: *const Node<C>) -> bool {n node as *const _ == &self.head as *const _n'I' }nn /// Walk the list and validate internal constraints. This is used forn /// test'I'ing the structure itself, and should gen'I'erally not be called byn /// users.n pub fn check(&self) {n // #[cfg(test)]n {n // self.print();n assert!(self.head.height'tem' >= 1);n assert!(self.head.height <= MAX_HEIGHT_U8);nn '' /// SAFETY: Self must outlast'm' the marker and not have been moved since then /// marker was created. Self should really be Pin<>!'n ''''''''''''''''''''''''''''y'f'i't'o'n' ',''''&''''''''''''''e''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''!'>''''&''''*'<'n'i'P' 'e'b' 'y'l')''l'a''('e'r''t' 't''d'l''h'u'o'h'g''s' ''i'f'l'e'e''S' ''h'.'d'e't'a'e'r'c' 's'a'w' 'r'e'k'r'a'm' 'e'h't' 'e'c'n'i's' 'd'e'v'o''.'m' 'n'e'e'b' 'e'v'a'h' 't'o'n' 'd'n'a' 'r'e'k'r'a'm'''''''''e'm'i't'e'f'i'l' 'e'h't' 't'''''''t' 's'a'l't'u'o' 't's'u'm' 'f'l'e'S''''''''m' 'e'h'T' ':'Y'T'E'F'A'S' '/'/'/' ' l''''''''''' 'e'f'a's'n'u'''''' 'e'f'a's'n'u'et head_ptr = &self.head as *const _ as *mut _;n // let skip_over = self.get_top_entry();n // println!('Skip over skip chars {}, num bytes {}', s' '''kip_over.skip_items, self.num_b' 'ytes);nn 'tem' let mut prev: [*con' 'st Node<C>; MAX_HEIGHT] = [ptr::null(); ' 'MAX_HEIGHT];nn let mut iter = [SkipEntry {n /' '''r'e't' '/ Bleh.n 'I''' node: head_ptr,n // The skips wi' '''r'e't' 'll store the tota'''r'e't'l distance travelle'I'd since' ' then // start of this trave' 'rsal at ea'tem'ch height. All th' 'e entries aboven ' ' // head.height are ignored tho''ugh.n ' ' skip_usersize' ': 0n ' ' }; MAX_HEIGHT];nn let mut num_items = 0;n let mut num_usercount = 0;nn' ' for (_i, n) in self.iter().enumerate() {n // println!('visiting {:?}', n.as_str());n if !self.is_head(n) { assert!(n.num_items > 0); }n assert!(n.height <= MAX_HEIGHT_U8);n assert!(n.num_items as usize <= NODE_NUM_ITEMS);nn // Make sure the number of items matches the countn let local_count = C::userlen_of_slice(n.content_slice());n assert_eq!(local_count, n.get_userlen());nn let expect_parent = if s'''''''y'f'i't'o'n'.'elf.is_h'I'ead(n) {n ptr::null() // The head's parent is nulln } else if n.height == self.head.height {n &self.head as *const _ // Max height nodes point back to headn } el'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'t'r'e's'n'i' 'n'o' 't'n'''''''n't'i'a'r't's'n'o'c' 'r'o't'a'r'e't'I'e'z'i'S''''I't'c'a'x'E' 'e'h't' 'x'a'l'e'r' 'o't' 'e'm' 's'd'e'e'N' '/'/'n'''// '''''''''''''ListIte''''''''':':'d't's''''''''>'m'e't'I'<'''''':'''''// ''''''' 'e'r'e'h'w' '''''''SkipLis''' ''fn from_iter<T: IntoIter'// 'ator<I' ' ''''te''m''''m'e't'I''' =' '// ' 'ne'// 'w_from_iter'''''''''m'o'r'f'_'w'e'n' 'SkipLis'''fro'''''r'e't'i'_'m''''r'e't'i'(iter: I)''''''''''w'e'n':':''''<'t'''''p'i'k'S' ' A>>(iter: T) -> S'''''' ''' }''n 'n ' '{' '''elf;''''''''''}''n 'n ' '{' '>'m'e't'I'<'t'''''p'i'k'S' 'r'o'f' ':'r'e't'i'''''''''''''r'o't'a'r'e't'I'm'o'r'F' '>'m'''''t's'i'L' ':'m'e't'I'<'l'p'm'i'''''''''''''''''''I'<'l'p'm'i'n''n'se {n prev[n.height as usize]n };nn // println!('visiting {} {:?}', i, n as *const _);n // dbg!(n as *const _);n // db'I'g!((n as *const _, (*n).height));n // dbg!(n.parent);n '''''''<'n'o'>''i't'p'O' //''''''''''''.'n'w'o'n'k' 'f'i''''o' ','''tem' dbg!(&self.head as *const _);nn assert_eq!(n.parent as *const _, expect_parent, 'invalid parent');n n for (i, entry) in iter[0..n.height as usize].iter_mut().enumerate() {n 'm' assert_eq!(entry.node as *const _, n as *const _);n assert_eq!(entry.skip_usersize, num_usercount);nn 'e' // println!('replacing entry {:?} with {:?}', 'tem'entry, n.nexts()[i].node);n prev[i] = n;n en't'try.node = n.nexts()[i].node;n 'n ''''''''''''(')''e'm'o'S''''=' 'r' ''''''''remain''{' 'ing_i' 'r''tems'''''a'm'e'r'.'f'l'e's'r'' 't'e'l' 'f'i' ' '' ''''''''n ''''''''''' }'n ')'e'n'o'N' ','0'(' '{' 'e's'l'e' '}'n ' entry.skip_usersize += n.nexts()[i].skip_usersize;n }nn num_items += n.num_items as usize;n num_usercount += n.get_userlen();nn // Check the value returned by the iterator functions matches.n let (mut normal_iter, local_offset) = self.iter_at_userpos(num_usercount);n assert_eq!(local_offset, 0);nn // Dirty hack. If n has 0-sized elements at the end,'r' th'e'e n'p'orm'u'aln's''''''''''''''''''''''''''''m'e't'I' '=' '''''''''' '+' 'd'e'z'i'S'?''''''''', Rhs: ?'''' where Item: PartialEq<Rhs>' 'Size'>'d'<''''>'s'h'R'<' ':'s'h'R' ','' '' '''s'h'R' '' // c''ursor w''on't be'' at the end...n while normal_iter.here_'pub(crate) ''// 'ptr() != n as *const _ as *mut _ {n normal_iter.advance_node();n }n norma'I'l_iter.loca'I'l_index = n.num_items as usize;n let node_iter = unsafe { self.iter_at_node(n, n.get_userlen(), n.num_ite'tem''''tem'ms 'tem'as usize) };n assert_eq!(normal_iter, node_iter);n }nn for entry in iter[0..self.head.height as usize].iter()'m' 'e'{'t'n // println!('{:?}', entry);n assert!(entry.node.'m'is_null());n assert_eq!(entry.skip_usersize, num_usercount);n 'I' }n n // println!('self bytes: 'e'{}, count bytes {}', self'Self::use_parents()'.num_bytes, num_'''N' ','bytes);n assert_eq!(self.num_items, num_items);n a't's'tem'sert_eq!(self.get_userlen'm'(), num_usercount);n }n }n n n /// I'e'nternal function for creating a cursor at a particular 't'location in then /// skiplist. The 'n '''''I''''''''I'PhantomDat'''': E'''x'I''xactSizeIterator<It'''x'em=Item>','a'I'''''''''x'n'a'h' where Ite': ExactSizeItera'I'''tor<Item=I'x'tem>'r''P' ''m':'r'e'k'r'a'm'_' 'retur'''x'ned'' cursor con''tains list o''f nodes which point pastn /// the specified position,'V' as well as offsets of how far into'e' theirn /// character lists the specifi'tem'ed char''acters are.n ///n /// Sometimes a call to iter_at_'T'userpos is ambiguous:n ///n /'t'// - The item can contain it'm'ems with zero usersiz''e. The cursor co'tem'uld po'tem'intn /// 'e' to any of t'm'hem.n 'I'/// - 'm'If the location is at the 't'end of a node, it is equally valid to returnn ///'m''' 'I'a position at the start of the next node'e'.''''ListItem'''''e'''I't's'i'L' 'I'''':'m''I''C:'I''''' L'm'istCo'I'nfig''I::get_usersize('n ///n /'e'// Because'V''I' it'm's imp'tem'ossi'tem'ble to move backwards 't'in'm' the list, ite't'r_at_userposn /'e'// retu'm'rns 'e'the f''irst admissible location with the specif't'ied user'e'pos.n'e' /'T'// n /// Returns (cursor'e', offset into the s't''tem'pecified item).n't' ///n 'm' /'t'// TODO: Thi''s sho'm'uld be Pin<'I'&self>.n fn iter_at_userpo't's(&self, targ'I'et'e'_userpos: usi't'ze) -> (Cursor<C>, usize) {n '' assert!(ta't'e''rget_userpos <= self.get_u''serlen());nn 'V' let 'm'mut e:'I' *const Node<C'I'tem': ListItem'> = &self.head;n l''N::notifica'I''''I'''t''ions_used('''&'''m'''e'&'t''t'''I' ')''' 'et mut height = self.h'm'ead.height'T' as'/'e'/ 'm'' usize'V' - 1;n n let mut of'e'fset = target_userpos; // How many more ite''ms to skipnn '' 't' // We're populating the head node pointe'I'r 't't'e'o simplify 'T'I''the case when then'm' // iterator grows. We could put offset'// ' into'''''n 'e' '''' ' the skip_usersize b'''r'e't'ut'I: ListIt't'em' it't'n 'C: ListC'I'V'''m'onfig''I: L'''r'e't'istItem' // would only'I' be *mostly* co''e'''r'e't'rrect, not always cor''''rect.'I''' (Since cu'm'rsorn 'I't'' // en''''I: Li''stItem'C''''I''T'''tries ''I'''I'a'e'bove height are'I' not updated 'I'''V''by insert.)n let mut cu't'rsor = Cursor {n'' entries: [SkipEntry {''n 'I' ''node: &self.he'I'ad as 'I'*const _ as *mut _,n 'V' 'I's'T'kip_usersize: usize::MAXn '' ')' 'I'}; '''('MAX_HEI't'GHT],n 'h' 'g' '' 'I'loc'i'I: L'V'i''stItem''al_inde'e'x: 0,'I'''n 'h' userp'T'os'I''': targe'I''I't_userpos,n };nn '' loop { // while height >= 0n '.' let en ='' unsafe { &*e };'T'n'' let next = en.nexts()[height];n 'I' let skip = next.skip_us'I: ListIte'I'm'e''rs''ize;n 'I' '' if')' offset >'(' skip {n 't' '' 'h' 'I' // 'g'Go right.'i'n 'e' d'h'ebug_assert!(e == 'n '_marke'''Pha'I: L'I'istIte''m'''ntomData'''''n'a'h'P' ':'r''''''k'r'a'm'_' '&self.head || en.num_items'.' > 0);n 'I' offset -= skip;n 'I' 'I: ListItem' e = next.node;n '' '' assert!(!e.is_null(), 'Internal constraint violation: Reached rope end prematurely');n } else {n // Record this and go down.n cursor.entries[height] = SkipEntry {n skip_usersize: offset,n node: e as *mut Node<C>, // This is pretty grossn };nn if height == 0 { break; } else { height -= 1; }n }n };nn // We should always land within the node we're pointing to.n debug_assert!(offset <= unsafe { &*cursor.here_ptr() }.get_userlen());nn // We've found the node. Now look for the index within the node.n 'y' let en = unsafe { &*e };n let mut index = 0;nn while offset > 0 {n assert!(index < en.num_items as usize);n n let usersize = C::get_usersize(unsafe { &*en.items[index].as_ptr() });n if usersize > offset { break; } // We're in the middle of an item.n offset -= usersize;n index += 1;n }n cursor.local_index = index;nn (cursor, offset)n }nn unsafe fn iter_at_node(&self, n: *const Node<C>, mut offset:'' usize, local_''index: usize) ->'y' Cursor<C> {n let mut n = n as *mut Node<C>; // We don't mutate, but we need a mut ptr.nn let mut cursor = Cursor {n userpos: 0, // We'll set th')'is later.n '(' 't'local_index'h': local_ind'g'ex,n 'i' entrie'e's: [SkipEnt'h'ry {n node: &self.head as *const _ as *mut _,n skip_usersize: usize::MAXn }; MAX_HEIGHT],n '.' };nn let mut h = 0;n loop {n while h < (*n).height as usize {n cursor.entries[h] = SkipEntry {n node: n,n 'y' skip_usersize: offsetn };nn h += 1;n }nn let parent = (*n).parent;n // R'r'eache'e'd the'p' head'u'.n 's' ''if parent.''is_null() ''{ break; }''nn '' // If we're the same height as the parent its fine.n''''''''''' ')'e't'a'r'c'(''''''''''r'c')'b'u'p''''''''y''''''impl<C: ListConfig, N: NotificationTarget<C>> fmt::Debug for SkipList<C, N> where C::Item: fmt::Debug {n fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n f.debug_list().entries(self.iter()).finish()n 'y'}n}'n'n'nimpl<C: ListConfig, N: NotificationTarget'''''''t'l'u'a'f'e'D'<C>> ''fmt::Deb'''''''t'''l'u'a'f'e'd'ug fo'SkipLis''''''')'('w'e'n':':'t'''k'S'''r SkipList<C, N> whe''''f'l'e'S're C::Item: fmt::Debug {n fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n f.debug_list().entries(self.iter()).finish()n }n}n'b'u'[''''''''''b'i'[' debug_assert!((*parent).height as usize > hn || (self.is_head(parent) && (*parent).height as usize == h));nn // Walk from parent back to n, figuring out the offset.n let mut c = parent;n // let walk_height = (*parent).height as usize - 2;n let walk_height = (*n).height as usize - 1;n while c != n {n let elem = (*c).nexts()[walk_height];n offset += elem.skip_usersize;n c = elem.node;n }nn n = parent;n }nn cursor.userpos = offset;n cursorn }nn pub fn iter_at_marker(&mut self, marker: ItemMarker<C>, query: &<C::Item as Queryable>::Query) -> Cursor<C> where C::Item: Que''ryable {n // The marker gives us a pointer into a node. Find the item.n unsafe {n let n = marker.ptr;nn let mut offset: usize = 0;n '// ' let mut local_index = None;n for (i, item) in (*n).content_slice().iter().enumerate() {n if let Some(item_offset) = item.contains_item(query) {n offset += item_offset;n local_index = Some(i);n break;n } else {n offset += C::get_usersize(item);n }n }nn let local_index = local_index.expect('Invalid marker - item not found in node');n self.iter_at_node(n, offset, local_index)n }n }nn // Internal fn to create a new node at the specified iterator filled withn // the specified content. The passed cursor should point at the end of then // previous node. It will be updated to point to the end of the newlyn // inserted content.n // unsafe fn insert_node_at(&mut self, cursor: &mut ''Cursor<C>, contents: &[C::Item], new_userlen: usize, move_cursor: bool) {n unsafe fn insert_node_at<Notify, 'N'I>(&mut self, cursor: &mut'' Cursor<C>, contents: &mut I, num_items: usize, move_cursor: bool, notify: &mut Notify)n where Notify: FnMut(&[C::Item], ItemMarker<C>), I: Iterator<Item=C::Item> {nn // println!('Insert_node_at {} len {}', contents.len(), self.num_bytes);n // debug_assert_eq!(new_userlen, C::userlen_of_slice(contents));n assert!(num_items <= NODE_NUM_ITEMS);n debug_assert!(contents.size_hint().0 >= num_items);nn let new_node_ptr = Node::alloc(self.get_rng());n let new_node = &mut *new_node_ptr;n 'pub(super) ' new_node.num_items = num_items as u8;nn for (slot, item) in new_node.items[..num_items].iter_mut().zip(contents) {n (slot.as_mut_ptr()'n ''''''''''''''''''''''''''''''''''''' '.'g'n'i'g'g'u'b'e'd' 'r'o'f' 't's'u'j''''''''''''e'd' 'r'o'f' 't'u's'j' 's'i' 's'i'h'T''''''''''''''''''''''' '.'s'i'h't' 't'r'''''''''' 't'e'o'p'x'e' 't'o'n' 'o'D' ':'O'D'O'T' '/'/' ' ''a'''''''('''''''''''f'l'e's''''''r'e'p'u's'''''''.'.''' 'n'i'''''''' ')'r'e'p'u's'('b'u'p''''s *''''''.'.'''''''''h't'a'p'''''''i'd''''''r'e'p'u's'mut C::Item).write(item); // Write m''''''')'e't'a'r'c'('akes sure we don't drop the old value.n }nn let new_userlen = C::userlen_of_slice(new_node.content_slice());nn let new_height = new_node.height;n let new_height_usize = new_height as usize;nn let mut head_height = self.head.height as usize;n while head_height < new_height_usize {n // This seems weird given we're about to overwrite these valuesn // below. What we're doing is retroactively setting up the cursorn // and head pointers *as if* the height had been this high alln // along. This way we only have to populate the higher head valuesn // lazily.n let total_userlen = self.num_usercount;n let nexts = self.heads_mut();n nexts[head_height].skip_usersize = total_userlen;n cursor.entries[head_height].skip_usersize = cursor.userpos;nn head_height += 1''; // This is ugly.n '''''' self.head.h''eight += 1;n }nn new_node.parent = if new_height_usize == MAX_HEIGHT {n &self.head as *const _ as *mut _n } else { cursor.entries[new_height_usize].node };nn for i in 0..new_height_usize {n let prev_skip = &mut (*cursor.entries[i].node).nexts_mut()[i];n let new_nexts = new_node.nexts_mut();nn // The new node points to the successor (or null)n new_nexts[i] = SkipEntry {n node: p''''''''y'f'i't'o'n'.'y''''.'rev_skip.node,n skip_usersize: new_userlen + prev_skip.skip_usersize - cursor.entries[i].skip_usersizen };nn // Th''e previous node points to the new noden '' *prev_skip = SkipEntry {n node: new_node_ptr,n skip_usersize: ''''cursor.entries[i].skip_usersizen };nn // Move the iterator to the end of the newly inserted node.n if move_cursor {n cursor.entr''''''''''''' ''''n' pub fn new_from_iter_n<I: ExactSizeIterator<Item=C::Item>>(iter: I, notify: &mut N) -> Self {n let mut rope = Self::new();n rop''n'_'e.in''''''''y'f'i't'o'n' ','sert_at(0, iter);n ropen }nn pub fn new_from_slice_n(s: &[C::Item], notify: &mut N) -> Self where C::Item: Copy {n Self::new_from_iter_n(s.iter().copied(), notify)n }nn pub fn edit_n<'a>(&'a mut self, userpos: usize, notify: &'a mut N) -> (Edit<C, N>, usize) {n assert!(N::notifications_used());n let (cursor, item_offset) = self.iter_at_userpos(userpos);n (Edit { list: self, cursor, notify }, item_offset)n }nn pub fn edit_between_n<'a>(&'a mut self, userpos: usize, notify: &'a mut N) -> Edit<C, N> {n let (cursor, item_offset) = self.iter_at_userpos(userpos);n assert_eq!(item_offset, 0, 'edit_between landed inside an item');n Edit { list: self, cursor, notify }n }nn pub fn replace_at_n<I: ExactSizeIterator<Item=C::Item>>(&mut self, start_userpos: usize, removed_items: usize, inserted_content: I, notify: &mut N) {n self.edit_between_n(start_userpos, notify).replace(removed_items, inserted_content);n }nn // pub fn replace_at_slice_n(&mut self, start_userpos: usize, removed_items: usize, inserted_content: &[C::Item]) where C::Item: Copy {n // self.replace_at(start_userpos, removed_items, inserted_content.iter().copied());n // }nn // pub fn modify_item_after_n<F: FnOnce(&mut C::Item, usize)>(&mut self, userpos: usize, modify_fn: F) {n // let (mut edit, offset) = self.edit(userpos);n // edit.modify_current_item(|item| modify_fn(item, offset))n // }nn pub fn insert_at_n<I: ExactSizeIterator<Item=C::Item>>(&mut self, userpos: usize, contents: I, notify: &mut N) {n let (mut edit, offset) = self.edit_n(userpos, notify);n edit.insert_between_iter(offset, contents);n }nn pub fn insert_at_slice_n(&mut self, userpos: usize, contents: &[C::Item], notify: &mut N) where C::Item: Copy {n self.insert_at_n(userpos, contents.iter().copied(), notify)n }nn // pub fn del_at_n(&mut self,''''t's'i'l' 't'u's's'i'erpos'l': usize, num_items: usize) {n // self.edit_betwee'n pub fn new_from_iter_n<I: ExactSizeIterator<Item=C::Item>>(iter: I, notify: &mut N) -> Self {n let mut rope = Self::new();n rope.insert_at_n(0, iter, notify);n ropen }nn pub fn new_from_slice_n(s: &[C::Item], notify: &mut N) -> Self where C::Item: Copy {n Self::new_from_iter_n(s.iter().copied(), notify)n }nn pub fn edit_n<'a>(&'a mut self, userpos: usize, notify: &'a mut N) -> (Edit<C, N>, usize) {n assert!(N::notifications_used());n let (cursor, item_offset) = self.iter_at_userpos(userpos);n (Edit { list: self, cursor, notify }, item_offset)n }nn pub fn edit_between_n<'a>(&'a mut self, userpos: usize, notify: &'a mut N't') -'s'> E'i'dit<C, N> {'l'n let (cursor, item_offset) = self.iter_at_userpos(userpos);n assert_eq!(item_offset, 0, 'edit_between landed inside an item');n Edit { list: self, cursor, notify }n }nn pub fn replace_at_n<I: ExactSizeIterator<Item=C::Item>>(&mut self, start_userpos: usize, removed_items: usize, inserted_content: I, notify: &mut N) {n self.edit_between_n(start_userpos, notify).replace(removed_items, inserted_content);n }nn // pub fn replace_at_slice_n(&mut self, start_userpos: usize, removed_items: usize, inserted_content: &[C::Item]) where C::Item: Copy {n // self.replace_at(start_userpos, removed_items, inserted_content.iter().copied());n // }nn // pub fn modify_item_after_n<F: FnOnce(&mut C::Item, usize)>(&mut self, userpos: usize, modify_fn: F) {n // let (mut edit, offset) = self.edit(userpos);n // edit.modify_current_item(|item| modify_fn(item, offset))n // }nn pub fn insert_at_n<I: ExactSizeIterator<Item=C::Item>>(&mut self, userpos: usize, contents: I, notify: &mut N) {n let (mut edit, offset) = self.edit_n(userpos, notify);n edit.insert_between_iter(offset, contents);n }nn pub fn insert_at_slice_n(&mut self, userpos: usize, contents: &[C::Item], notify: &mut N) where C::Item: Copy {n self.insert_at_n(userpos, contents.iter().copied(), notify)n }nn // pub fn del_at_n(&mut self, userpos: usize, num_items: usize) {n // self.edit_between(userpos).del(num_items)n // }n'n(userpos).del(num_items)n // }n' 'n ' 'n ' 'n ' 'ies[i] = SkipEntry {n node: new_node_ptr,n '' '''' skip_usersize: new_userlenn };n }n 'N' }nn '' '' for i in new_height_usize..head_height {n (*cursor.entries[i].node).nexts_mut()[i].skip_usersize += new_userlen;n if move_cursor {n cursor.entries[i].skip_usersize += new_userlen;n }n }nn // Update parents.n'nn pub fn edit(&mut self, userpos: usize) -> (Edit<C>, usize) {n let (cursor, item_offset) = self.iter_at_userpos(userpos);n (Edit { list: self, cursor, notify: unsafe { &mut NULL_NOTIFY_TARGET } }, item_offset)n }nn pub fn edit_between(&mut self, userpos: usize) -> Edit<C> {n let (cursor, item_offset) = self.iter_at_userpos(userpos);n assert_eq!(item_offset, 0, 'edit_between landed inside an item');n Edit { list: self, cursor, notify: unsafe { &mut NULL_NOTIFY_TARGET } }n }' if new_height_usize > 1 {nn let mut n = new_node_ptr;n let mut skip_height = 0;nn loop {n n = (*n).nexts_mut()[skip_height].node;n if n.is_null() || (*n).height >= new_height {'impl<C: ListConfig> SkipList<C> {n pub fn new_from_iter<I: ExactSizeIterator<Item=C::Item>>(iter: I) -> Self {n let mut rope = Self::new();n rope.insert_at(0, iter);n ropen }nn pub fn new_from_slice(s: &[C::Item]) -> Self where C::Item: Copy {n Self::new_from_iter(s.iter().copied())n }nn pub fn replace_at<I: ExactSizeIterator<Item=C::Item>>(&mut self, start_userpos: usize, removed_items: usize, inserted_content: I) {n self.edit_between(start_userpos).replace(removed_items, inserted_content);n }nn pub fn replace_at_slice(&mut self, start_userpos: usize, removed_items: usize, inserted_content: &[C::Item]) where C::Item: Copy {n self.replace_at(start_userpos, removed_items, inserted_content.iter().copied());n }nn pub fn modify_item_after<F: FnOnce(&mut C::Item, usize)>(&mut self, userpos: usize, modify_fn:'' F) {n let (mut edit, offset) = self.edit(us''erpos);n edit.modify_current_item(|item| modify_fn(item,'' offset))n }nn pub fn insert_at<I: ExactSizeIterator<Item=C::Item>>(&mut self, userpos: usize, contents: I) {n let (mut edit, offset) = self.edit(userpos);n edit.insert_between_iter(offset, contents);n }nn pub fn insert_at_slice(&mut self, userpos: usize, contents: &[C::Item]) where C::Item: Copy {n self.insert_at(userpos, contents.iter().copied())n }nn pub'''_target''' ''f''n'' ''d''e''l_at(&mut self, userpos: usize, num_items: usize) {n s'n'elf.edit_between(userpos).del(num_items)n }nn pub fn edit(&mut self, userpos: usize) -> (Edit<C>, usize) {n let (''cursor, item_of''''>'''' 'a'''a'''<'fset) = self.iter_at_u'nn '' // pub''' 'a'''' ''' fn edit_b''n'_''''N' ','etween(&mut self, user''''''''''''''''N' 't'u'm'&' ':'y'f'i't'o'n' ','pos: usize) -> Edit<C> {n '' // let (cursor, item_offset) = self.iter_at_userpos(userpos);n '' // assert_eq!(item_offset, 0, 'edit_between landed inside ''an item');n '' // Edit { list: self, cursor, notify: uns''''''''''''''''N' 't'u'm'&' ':'y'f'i't'o'n' ','afe { &mut NULL_NOTIFY_TARGET''n'_' } }n ''''''''''y'f'i't'o'n' ',' // }'serpos(userpos);n (Edit { list: self, cursor, notify: unsafe { &mut NULL_NOTIFY_TARGET } }, item_offset)n }nn pub fn edit_between(&mut self, userpos: usize) -> Edit<C> {n let (cursor, item_offset) = self.iter_at_userp'''n 'n pub fn edit_n<'a>(&'a mut self, userpos: usize, notify_target: &'a mut N) -> (Edit<C, N>, usize) {n assert!(N::notifications_used());n let (cursor, item_offset) = self.iter_at_userpos(userpos);n (Edit { list: self, cursor, notify: notify_target }, item_offset)n }' 'os(userpos);n assert_eq!(item_offset, 0, 'edit_between landed inside an item');n Edit { list: self, cursor, notify: unsafe { &mut NULL_NOTIFY_TARGET } }n }n}n' break; }''n ''''''NotificationTarge'''>'C'<'t''''''''N''' '' ',''f'i't'o'N'''''''''''''''''N' 't'u'm''''n'&' ':''''&'y'f'i't'o'n' ','''i'''n'_'L'''n'_' ':'N' ',' n'''''''''y'f'i't'o'n' ','' (*n'''''''''' ':'y'f'i't'o'n'''''''N''''n' 't'''u'm'&' ',').parent = new_nod'''''''''''''''ULL_NOTIFY''_'N''''''')'(' ':''''''''''';')'(' '=' ''''''''''''')'(' ':'''''''''''''''''N''''n' 't'u'm'&' ':'y'f'i't'o'n' ','T'E'G'R'A'T' 't'u'm' '''n'_''n'_''c'i't'a'''''''''y'f'i't'o'n' ','t's'n'n'e_ptr;''n'_'n skip_height = usize::max(skip_height, (*n).height as usize - 1);n }n '' 'n ' '' pub fn new_from_iter<I: ExactSizeIterator<Item=C::Item>>(iter: I) -> Self {n let m'// 'ut rope = Self::new();n 'n' '_' rope.insert_at(0, iter)''n'_';n ''''''''y'f'i't'o'n' ',' ropen }nn pub fn new_from_slice(s: &[C::Item]) -> Self where '// 'C::Item: Copy {n Self::new_from_iter(s.iter().copie'''''n 'd())n }n' ' }n'// ' '// ' n self.num_items += n'n'um_'_'items;n self.num_usercount += new_userlen;n if move_cu'// 'rsor {n cursor.userpos += new_userlen;n '//'' ''' cursor.local_index = num_items;n }nn not''if'// 'y(new_n'// 'ode.content_slice(), It'n'emMar'_'ker {n ptr: new_node_ptr,n ''''''''''''''''N' 't'u'm'&' ':'y'f'i't'o'n''''N' ',' _p''hantom: PhantomD'// 'atan });n }nn // unsaf''e fn insert_at_ite'/''/ 'r(&mut self, cursor: &mut Cursor''<C>, contents: &[C::'// 'Item]) '// '{n unsafe fn insert_at_iter<'n'Notify,'_' I>(&mut self, cursor: &mut Cursor<C>, contents: &mut '''// ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''// '''''''''// '''''.'t'e'g'r'a'''n 'n pub fn edit_n<'a>(&'a mut self, userpos: usize, notify_target: &'a mut N) -> (Edit<C, N>, usize) {n assert!(N::notifications_used());n let (cursor, item_offset) = self.iter_at_userpos(userpos);n (Edit { list: self, cursor, notify: notify_target }, item_offset)n }' ''t' 'n'o''n'i't'a'c'i'_''f'i't'o'n' 'o'n' 's'''e'r'e'// ''h't' 'f'i' 'e'l'b'a'l'i'a'v'a' 'y'l'n'o' 'e'r'a' '// ''s'd'o''// 'h't'e'm' 'e's'e'h'T' '/'/'n'''''''''''ListConfi'''SkipLis'''''''''// ''n pub fn replace_at<I: ExactSizeIterator<Item=C::Item>>(&mut se'// 'lf, start_userpos: usize, removed_items: usize, inserted_content: I) {n self.edit_betwee'// 'n(start'// '_userpos).replace(removed_items, inserted_content);n }nn p'// 'ub fn replace_at_slice(&mut self, start_userpos: usize, removed_ite'// 'ms: usize, inserted_content: &[C::Item]) where C::Item: Copy {n sel'// 'f.replace_at(start_userpos, removed_items, inserted_content.iter().copied());n '// ' }nn pu''''''''' '{' ''ULL_NOTIFY'e'f'a's''}' ''n'u'b fn ''''''''T'E'G'R'A'T'_'N'''m''odify_item_after<F: FnOnce(&mut C::Item, usize)>(&mut self, userpos: usize, modify_fn: F) {n let (mut edit, offset) = self.edit(userpos);n edit.modify_current_item(|item| modify_fn(item, offset))n }nn pub fn i'unsafe { &mut 'ULL_NOTIFY'N_TARGET }'nsert_at<I: ExactSizeIterator<Item=C::Item>>(&mut self, userpos: usize, contents: I) {n let (mut edit, offset) = self.edit(userpos);n edit.insert_between_iter(offset, contents);n }nn pub fn insert_at_slice(&mut self, userpos: usize, contents: &[C::Item]) where C::Item: Copy {n self.insert_at(userpos, contents.iter().copied())n }nn pub fn del_at(&mut self, userpos: us''i''ze, num_items: usize) {n self.edit_between(userpos).del(num_items)n }nn pub fn edit(&mut self, userpos: usize) -> (Ed''it'')'('''<C, impl FnMut(&[C::Item], ItemMarker<C>)>, usize) {n /''/ self.edit_notify(userpos, no_notify_x::<C>, f)n let'' (cursor, item_offset) = self.iter_at_userpos(u''''' 't'u'm'&''''')'('serp''o''s);n ')' assert!(!N::notifications_used());n (Edit { list: self, cursor, notify: Self:'':no_n')'o'('tify }, item_offset)n }nn pub fn ''edit_between(&mut self, userpos: usize) -> Edit<C, impl FnMut(&[C::Item], ItemMarker<C>)> {n // self.edit_notify(userpos, no_notify_x::<C>, f)n '''''''''''''''''''''''''''''''''''''''''''.'t'e'g'r'a't' 'n'o'i't'a'c'i'f'i't'o'n' 'o'n' 's'''e'r'e'h't' 'f'i''''w' 'y'l'n'O' '/'/'n' ' ' 't'l'u'e'm'imp'<''C: ListConfi', N: Noti''f''i''cationTarget<C>'''''''''''''_''N''' ':'N' ',''''_''''N'''g, N: Notifi'_'''''''''cationTarget<C>>'''l<C: Lis'C, N'''t''C''o''nfig, N: NotificationTarget<C>> ''impl<C:'''N' ',' ListConfig> SkipList<C> ''impl<C: ListConfig, N: NotificationTarget<C>> ''t'&' (cur''sor, item_offset')') ='(' self.iter_at_u')'serpos(userpos);n assert_eq!(item_offset, 0, 'edit_between landed inside an item');n Edit { list: self, cursor, notify: Self::no_notify }n }'''}''n 'n ' '{' '>''''''''''''')'(' ','C'<'t''''i'k'S' '>'g'''''t's'i'L' ':'C'<'''' 'l'p'm'i'n'I, notify: &mut Notify)n where Notify: FnMut(&[C::Item], ItemMarker<C>), I: ExactSizeIterator<Item=C::Item> {n // iter specifies where to insert.nn let mut e = cursor.here_ptr();nn // The insertion''''''NotificationTarge'''>'C'<'t''''''f'i't'o''''N''''C' ','N' ':'N' ',' offset into the destination no'impl''' ','I'<C: ListConfig, N: NotificationTarget<C>> ''impl<C: ListConfig,'' N',' I> ''impl<C: ListConfig, N: NotificationTarget<C>> 'de.n asse'''N' ','rt!('''''''N' ','cursor.userpos <= self.num_usercount);n 'impl<C: ListConfig, N: NotificationTarget<C>> ' assert!(cursor.local_inde'' N','x <= (*e).num_items as usize);nn // We'impl<C: ListConfig> ' mi')'ght be 'impl<C: ListConfig, N: NotificationTarget<C>> 'able t'('o insert the 't'n'''''''N' ','ew data into'h' the current 'g'node, dependi'i'ng onn 'e' // how big i'h't is.n let num_inserted_items = contents.len();nn // Can we insert into the current node?n let mut insert_here = (*e).num_items as usize + '.'num_inserted_items <= NODE_NUM_ITEMS;nn // Can we in'I: ExactSizeIterator<Item=C::Item>'''sert into the start of the successor node?n if !insert_here && cursor.l''o'n 'assert!'!'(N::notifications_used());' '''c''a''l''_''i''n''dex == (*e).num_items as usize && num_inserted_ite'edit_betwee'''''''''n ''''''' 'n'f' 'b'''''''b' 'u'p' 'n ' '''n''''(userpos: ''''''''a''''''''''>'''' 'b'''a''' ':'b''' ','a'''<'usize)'ms <'''''' 'a'''''w't''''''''''''''''t'e'g'r'a't'_'y' -> (Edit<C, N>, usize)''f'i't'o'n' ''e'b'_'= NODE_NUM_ITEMS {n // We can insert into the subsequent node if:n // - We', N: NotificationTarget<C>' can't insert into the cu'''N' ','rrent'''''''' ':'y'f'i't'o'n' noden // - There _is_ a next node to insert inton // - The '''''r'e't'f'a'''t'a''''n '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 't'u' ''''''''''''notifications_us' '' // let (cursor, item_offset) = self.iter_at_userpos(userpos);n '' // (Edit { list: self, cur'''''''t'e'g'r'a't'_'sor, notify }, item_offset'')n''n 'ed('';')')':':'N'('!'t'r'e's's'a' ''m'&'''''''':':'N' ':'t'e'g'r'a't'_'y'f'i't'o'n' ','''''''' ''' }''n 'n ' '{' ')''''''' ','e'z'i's'u' ':'s'o'p'r'e's'u' ','f'l'e's' 't'u'm'&'(''''<''''('y'f'i't'o'n'_'t'i'd'e' 'n'f' 'b'u'p' ''''''''''''''r'e''''''''e'z'i's'u' ','t'f'a'''i''nsert would be at the' let (mut edit, offset) '// '= self.e'n '''''''''''''''''''''''''modify'''''''')'(' '=' ''''''' '='''''t'n'e'r'r'u'c'_next''' // self.edit_between(userpos).modify_n'// 'ext_item(modify_fn)n'''_ite'''''''''modif''y''_''f''''''''''''''''''// ''''n '''''''''' '''' ''' '// ' }''n 'n ' '{' 'e's'l'e' '}' ')')'t'e's'f'f'o' ','m'e't'i'('n'''''i'd'o'm' '|'m'e't'i'|'('m'''''i'd'o'm'.'t'i'd'e' '{' '0' '// ''='=' 't'e's'f'f'o' 'f'i' 'dit(userpos);n' start of the next noden // - There's r': FnOnce(&mut C::Item)'oom in the next noden if let '''F: '''S''''': FnOnce(&mut C::Item)'o''m''e''(''n''e''x''t'')'' = (*e).first_skip_en''try_mut': ExactSizeIt''e''' '''' 't'u'm' '// ' self.edit_between(userpos).insert_iter(conten'n '''''''''''''''''''''''''''''''''''''''''n ''''''insert_between_iter''''''t'''''''''s';''''t'n'e't'n'o'c'e's'f'f'o'(offset: usize, mut contents: I)''''''r'e's'n'i'.'t'i'd'e' ';')'s'o'p'r'e's'u'('t'i'd'e'.'f'l'e's' '=' ')'t'e's'f'f'o' ','t'i'd'e'(' 't'e'l' 'ts)n'rator<Item=C::Item''> '().node.as_mut() {n '' '' ')'''' ''' '' ''i''f'' next.num_it''e'e''dit_between(userpos: usize)'ms as usiz'w'e't' 'e'+'b' '_'num_inserted_items <= NODE_NUM_ITEMS {n cursor.advance_node();n '' e = ne''xt;nn insert_''here = tr'edit_between(userpos: usize)'ue;n 'w' 't' 'e' }'b'n '_' }n }nn let item_idx = cursor.local_index;n let e_num_items = (*e).num_items as usize; // convenience.nn if insert_here {n /''/ println!''('insert_here {}', contents);n // Fir''st push the current 'edit_between(userpos: usize)'items later in'w' the 't'array'e'n 'b' '_' let c = &mut (*e).items;n '' i''''' 't'u'm'&'f item_idx < e_num_items {n // Can't use copy_within because Item doesn't necessarilyn // implement Copy. Memmove the existing items.n ptr::copy(n &c[item_idx],n &mut c[item_idx + num_inserted_items],n'''n ''''''''''''''''''''(&mut self, userpos: usize) ->'' (Edit<C, impl FnMut(&[C::Item], ItemMarker<''C>)>, usize) {n // self.edit_notify(userpos, no_notify_x::<C>, f)n let (cursor, item_offset) ='t' self.iter_a''t_userpos(use''rpos)'n '' 'assert_eq''''item_offse''''''''''''''''''''''''''''''''''''''''''''''''';')'''m'e'''t'i' 'n'a' 'e'd'i's'n'i''''b' 'd'e'd'n'a'l''''''''' 'd'n'u'o'f' 'n'e'e'w't'e'b'_'t'i'd'e'''''''' 't'o'n'n'a'C''' ','0' ','t'''''''o'_'m'e't'i'('!'''s'a' ';n (Edit { list: self, cursor, notify: Self::no_notify }, item_offset)n }''''_'n''''('e'e'w't'e'b'_'t'i'd'e' 'n'f' 'b'u'p' 'n ' ' (*e).num_items as usize - item_idx);n }nn // Then copy in the new items. Can't memcpy from an iterator, butn // the optimizer should make this fast.n let dest_content_slice = &mut c[item_idx..item_idx + num_inserted_items];n for (slot, item) in dest_content_slice.iter_mut().zip(contents) {n // Do not drop the old')' items - they w'('ere only moved.'t'n 'h' slot.as_mut_p'g'tr().write(item'i');n 'e'}n '' '''''''''''''':'' '''a'''''''''''''','a''' ':'b''' ' l'a''''h'et dest_cont'''Notifi'b'''cationTarge'''>'C'<'t'''''i't'o'N''''SkipListNotify'ent_slice '''N' ','= maybeinit_slice_get_ref(d','est_content_slice);nn 'a''' (*e).num_''' 'b'''items += num_''''''N' 't'u'm'&'inserted_items as u8;n self.num_items += num_inserted_items;n '.' let num_inserted_usercount = C::userlen_of_slice(dest_content_slice);n self.num_user')'count += num_inse'('rted_usercount;'<'a, C: ListConfig, N: NotificationTarget<C>>'nn't' // ..'h'.. aaaand update 'g'all the offset am'i'ounts.n 'e' cursor.update_o'h'ffsets(self.head.height as usize, num_inserted_usercount as isize);nn // Usually the cursor will be discarded after one change, but forn // consistency of compound edits we'll update t'.'he cursor to point ton // the end of the new content.n for entry in cursor.entries[0..self.head.height as usize].iter_mut() {n entry.skip_usersize += num_inserted_usercount;n }n cursor.userpos += num_inserted_usercount;n cursor.local_index += num_inserted_items;nn notify(dest_content_slice, ItemMarker {n ptr: e,n _phantom: PhantomDatan });n } else {n // There isn't room. We'll need to add at least one new node to then // list. We could be a bit more careful here and copy as much asn // possible into the current node - that would decrease the numbern // of new nodes in some cases, but I don't think the performancen // difference will be large enough to justify the complexity.nn // If we're not at the end of the current node, we'll need to removen // the end of the current node's data and reinsert it later.n let num_end_items = e_num_items - item_idx;nn let (end_items, _end_usercount) = if num_end_items > 0 {n // We'll mark the items as deleted from the node, while leavingn // the data itself there for now to avoid a co''py.nn // Note that if w''''t'x'e'n'''e'' ''w''anted to, it would also be correct (andn // slightly'prev_' more space efficient) to pack some of the newn // string's characters into''''' 't'u'm'&' this node after trimming it.n let end_items = &(*e).items[item_idx..e_num_items];n (*e).num_items = item_idx as u8;n let end_usercount = (*e).get_userlen() - cursor.entries[0].skip_usersize;nn cursor.update_o''''m'_'ffsets(self.head.height as usize, -(end'('_usercount as isize));nn // W'''''''')'e'z'i's'u' ','e need to trim the size off because we'll add the charactersn // back with insert_node_at.n self.num_usercou'(''''('nt -= end_usercount;n '''item_offset, ' ''''item_offse')'''t'', ' ','' self.num_items -= num_end_items;nn (Some(end_items)'(', end_us'''''''')'e'z'i's'u' ','ercount)n } else {n (None, 0)n };nn // Now we insert new nodes con'('taining the new character dat'it')'em_''offs''et, 'a' '.',' Then '' // data is broken into pieces with a maximum size of NODE_NUM_ITEMS.n // As further optimization, we could try and fit the last piece inton ''''.')' // the start of the subsequent n''ode.n let mut items_remaining = num_inserted_items;n while items_remaining > 0 {n let insert_here = usize::min(items_remaining, NODE_NUM_ITEMS);n self.insert_node_at(cursor, contents, insert_here, true, notify);n items_remaining -= insert_here;n }nn ''n // self.modify_at(start_userpos, Self::no_notify, |item, offset| {n ''.')''' // assert''_''eq!(offset, 0, 'replace_at must modify the entire item');n // *item = n // })'n''''' '''' // TODO: Consider re'''// 'cursively calling '.'i')'nsert_at_iter''(''''''''FnMut(&[C::Item], ItemMarker<C>)' 'l'p'm'i' ',') ''here inst''ea'// 'dn '''// ' // of making a whole new node'n ''''''''{' '' 'e'f'a's'n'u' ' for'' the'// ' remaining content.n ' '''' '// ' '' '' '' '// '''n 'n' ' s' 'elf.''unwrap'''''''t''''''c'e'p'x'e''''''''')'('p'a'r'w'n'u'''.'m' ''notif''y''(items: &[C::Item], at_marker: ItemMarker<C>)'''''i't'o'n'.''' 'odify_at(start_user'//' ' 'pos, Self::no_noti''fy, |ite'// 'm, offset| {n ''''''FnMut(&[C::Item]' ', ItemMarker<C>'>')' ':'N'<'''n // pub fn edit<F,'N' R>(&mut s' 'elf, userpos''''' 'l'p'm'i''''''''t'u'M'i'''''N' ','n'F':'l' u'n'size, ''f: ' 'F) -> Rn // where F: FnOnce(&mut Edit<C>) -> R {n // // self.ed' 'it_notify(userpos, no_notify_x::' '<C>, f)n // let (cursor, item_offset) = self.iter_at_userpos(userpos);n // ' ' let mut edit = Edit { list: self, cursor, item_offse'' }'n 't, not', notify' ': fn(&[C::Item], ItemMarker<C>')''''')'''''','''' ''f'':'' F) -> R'''ify: Self::no_notify };nn // // TODO: Or may''be I should pass o'node_'wnership here?n // f(&mut edit)n //'' ''}''''' assert_eq!(offset, 0, 'rep''.'// ')''l''ace_at must modify t'// 'he en''tire i'prev''current'tem');n *item = n ' // pub fn edit<F, R>(&mut sel''f'i'prev''''''''t''''''''t'n'e'r'r'u'c'n'e'r'r'u'c'', userpos: usize,'' f: '>'F) -> ''Rn'>' // whe'prev''''''''''t'n'e'r'r'u'c'''''''''re F: F''nOnce(&mut Edit<C>) -> R {n // // s'{'e''lf.edit_notify(userpos, no_notify_x::<C>, f)n // let (curs', notify: fn(&[C'n'::Item], ItemMarker<C>), f: F) -> R''''''''''''''''''''n where F: FnOnce(&mut Edit<C>) -> R '''' '''>'C'<'t'i'd'E' '>'-' ')'''o'''''''n ''''''''''''''''''''''''''''ListIte''''''' 'ListIte'''n ''''''''''''''&'i''''''''he''n '''''''''' }'n '0' ':'x'e'd'n'i' ','a''''''_'e'd'o'n')'d''''''a'e'h'.'f'l'e's'('e'm'o'S' ':'e'd'n pub fn prev_item(&self) -> Option<&C::Item> {n unsafe { self.cursor.prev_item() }n }n''o'n' '{' ''''t'x'e'n''''''''''r''''''I't's'i'L' ''' }''n '' ''' '''''''t'n'e'r'r'u'c''''''''''m'e't'i'_'t'''''''''''''i't'_'T'x'e'n' ''n'' '' ' '{' '>'C'<'r''''''I't's'i'L' '>'-' ')'f'l''''b'u'p'e's'&'('r'e't'i'_'''''_'v'e'r'p''m'e't'i' 'n'f' 'b'''u'p' 'n''''t'x'e'n' ' 'r, item_offset'''''''''{' 'e'f'a's'n'u' ') = self.i''}' 'te''r''_at_userpos(userpos);n '''''''t''''''''''''''''''''''''''''''''''''''''''''''''''''''.'v'e'r'p' 'y'f'i'd'o'm' 't'o'n'n'a'C' '.'t'n'e'm'u'c'o'd' 'f'o' 't'r'a't's' 't'a' 'r'o's'r'u'C''''''''''''''y'f'i'd'o'm' 't'o'n'n'a'C''''''''''o'm' 't'o'n'n'a'c'''''''r'o''''p's'r'u'C'''''''a'C''''c'e'p'x'e''unwrap()'''n'u'.''' '' // let mut ''''t'x'se'current'lf.cursor.curr''en'next''''''''''t'n'e'r'r'u'c'''''''t_item_mut()''''''e'n'''e''d''i'''self.cursor.prev_item_mut('')'t = Edit { list: self, ''cursor, item_of';'n // TODO: Or maybe I should pass ownership here?n f(&mut edit)'n'''f''s''et, notify: Self::no''_notify };nn '''// '''/''/'' ''}''' ''' '' ''// TODO: Or maybe I should pass ownership h''ere?n // f(&mut ed''it'// ')n '' // }n' '' })' ''''''//'// ' 'n '' ' ' '' '// ' '' if'''''''''''' '''>'C'<'t'i'd'E''' let Some(e''nd_items'// ') = en'/''''/ 'd'// '''_item'' '''// 's'''// ' {n '' '' '' '/'''''_'v'e'''''''r'p'''/'' ''' /''/ '// 'Passin'''''_'v'e'r'p'g'' false t'// 'o in'/'''''// '/ '''dicate we''// '// ' don't wa''nt'' ''the cursor'' u'// 'pdate'// 'dn '' '// '''' notify''''' ':'N''''FnMu'// 't(&[C::Item], ItemMarker<C>)' ',''''N' ',':'fn''''''''''''''e's'l'a'f'''''t'u'M'n'F' ''// 'l'p'm'''i' fn(&[C::Item], ItemMarker<C>)n' '// ' //''// '// ' af''ter this - it sh''''''_'e'd'o'n''o''u''// ''ld remain at the end ''of th'// 'e n'''''// 'ewlyn '// ' // i'// '''nserted cont''ent, whi'mIte'ch is *before* this en''d bit.n '' self.in'// 'ser''n ''''''''''''''''''''''''''''''e'u''''e'r't'''''''''''''''.'t'n'i'h'_'e'z'i's' ''''''' 'e'r'o'F' '/'/' 'e'z'i's'u' ':'s'm'e't'i'_'g'n'i'n'i'a'm'e'r' ','t_'n'node_at(cursor, &mut UninitOwne''dIter::'n '''mIte''''// '''''edit'''''''''''''s''// ''''''''''n ''''''''' 'b'u'p''''replace_a'''''''''''''''''''''''''''''''''''';')'t'n'e't'n'o'c'_'d'e't'r'e's'n'i' ','s'm'e't'i'_'d'e'v'o'm'e'r'('t''''''a'l'p'e'r'.'t'i'd'e' ''' }'n '{' '|'t'i'd''''''''''t'd'i'e'|'o'p'r'e's'u'_'t'r'a't's'(u''''serpos: usize, f: F)''''i'd'e'.'f'l'e's' '<C>' pub fn modify'''''_'m'e't'i'_'''''''nstruct''''t's'i'L' NodeIte''''''.'f'l'e's''remaining_i''''''remaining_item'')')'s'.'''''''n'i'n'i'a'm'f'l'e's'tem''''''''''''f'l'e's''''''''''e'r'('e''''m''''''''''('e'z'm'o'S' ','s''remai'''g'n'i'n'''''''n'i'a'm'e'r'('''r<'a, C'''n '''''' ':'e'd'o'n''''n ''''size_hint'''''f'l'e's'&'('''''''''<'''''>'''''''''''''''''''''''n 'unimplemente''')'('!'d'''''''l'p'm'''i'''n'u''' ''''''' }'n '{' ')'''' ')'e'z'i's'u'('n'o'i' unsafe {' '''n if self.item_offset == 0 {n'' '' '' '' ' ' ''''t'p'O' ','e'z'i's'u'(' '>'-' ')''''''''''z'i's' 'n'f' '' '''''r'e't'i'_' 'n ' ' '' ''n'''{''' ''''' 'n ''''''' ':'x''' '''}'n ''''e'd'n'i' ','''''': ListConfig>(Option'''''''e''' 'n ' let num_inserted_items = contents.len();n let start_userpos = self.cursor.userpos;n' 'z'i'''s'u' ','<'' 'n ' let current_item = self.cursor.current_item();' 'n le''''''t'e's'f'f'o't (start, end) = C::split_item(current_item, self.item_offset);' 'n // Move the cursor back to the start of the item we're''t' 'e' 's' 'f' 'f' 'n 'o' // splitting.' 'n self.cursor.move_to_item_start(self.list.head.height, self.item_offset);' 'n // This feels pretty inefficient; but its probably fine.' 'n self.list.replace_item(&mut self.cursor, start, &mut self.notify);n' 'n // TODO: Consider concatenating end into contents then just call' 'n // insert_at_iter once.' 'n self.list.insert_at_iter(&mut self.cursor, &mut con'' 'n ' pu''''''''n'e'e'w't'e''''''''''''''','e'z'i's'u' ':'t'e's'f'f'o' ''b'_'b f''''''''_'n'e'''''''' ','t'e's'f'f'o''e'w't'e'b'n insert(&mut self, item: C::Item) {n self.insert_iter(iter::once(item));n }' ''''n 'tents, &mut self.notify);n' 'n self.dbg_check_cursor_at(start_userpos, num_inserted_items);n' 'n self.list.insert_at''_iter(&mut self.cursor, &mut iter::once(end), &mut self.notify);' '&'a Node<C>>);nimpl<'a, C''''''''r'e't'I't's'i'L': ListConf''n ''''''''''''''''''''''''''''''''n ''''''''''''s' 'n'f' 'n ' ''''''''''''' '''''''''''''''&'''''''''''''''''''''''''n '''''''''''''''')'('h's'i'n'i''''-'f'.')')'('r'e't'i' '''''''''''''''''''n '' ''''''' ''''''''''''''''''''num_item'''''''''e'z'i's'u'' ' 's'a' ''''n 'get_next_ptr()''''''n'_'t'e'g''' ''''''''''''''''n ' ' '' '''''''''''''unsafe { '''e'd'o'n.first_skip_entry().node.' 'as_ref() ';'''}''''''''''''''''''''// ''''''';')'('e'd'o'n'_'t'x'e'n'.'''''''n'.'e'd'''''''''' '''''''''''''''''''g'u' ''// ''b'e'D'''' ':'''' '' ':'t'm'f' ':'m'e'''t'I':':'C' 'e'''''':':'t'm'''// ''''''''':':'t'f'' 'r'e'h'w' 'o'n'.'f'''l'// ''e's' '//'' ''=' 'e'd'o'n'.'f'l'e's' '' ';'0' '=' 'x'e'd'n'i'.'f'l'e's''' ''' }'n '{''' '''s''''m'u'''n'.'''''''''''''n'e'l'.'e'd'o'n' '='='''''''''' '='=' 'x'e'd'n'i'.'f'l'e's' 'f'i' ';'1' '='+' 'x'e'd'n'i'.'f'l'e's''''''''''''''''''''''''1' '+' 'x'e'd'n'i'.'f'l'e's' 'f'i' ''''''n '' '''''('e'm'o'S'&''*'''''''''''''''r't'p'_'s'a''' '{' 'e''')'''''''''''}' ')'' ''''''''''''''''''''''''''''f'l'e's'''''''insert_ite''''''''''''''''n '}' ';')'s't'n'e't'n'o'c'('r'''''''''i'_'t'r'e's'n'i'.'s'i'h't'''''''n'i' 'n'r'u't'e'r' '{' '0' '='=' 't'e's'f'f'o' 'f'i' '('f'e'r'_'t''''n ''''''''''''''''''''''''''<I>(&mut self''''''''''''''','e'z'i's'u' ':'t'e's'f'f'o' ', mut contents: I) where I: Ex''' }''n 'n ' 'actSizeIterator<Item=C::Item> {'n'e'e'w't'e'b'_'t'r'e's'n'i' 'n'f' 'b'u'p' 'n ' 'e'g'f'a's'n'u'''''''''.'t'n'e'r'r'u'c' 'n '' ' ';']'x'e'd'n'i'.'f'l'e's'['s'm'e't'i'.''''['e'd'o'n' '='n ''''''''''''''''''''''''''''''''''''''''''''''''''m'e't'i' 't'x'e'n' 'e'h't' 'o't' 'r'o's'r'u'c' 'e'h't' 's'e'v'o'm' 's'i'h'T' ':'t'a'e'v'a'C'''''' 's'i'h'T' '/'/'/' '' 't'n'e'r'r'u'c''''e't'i' 't'e'l' ''' ''''''''''''''}' ''''''n 'e'n'o'N' '{' 'e's'l'e' '}''n 'n ' '{' 'e'd'o'n'.'f'l'e's' '=' ')'e'd'o'n'''('e'm'o'S' 't'e'l' 'f'i'''''''''' '''''''''''''''_'s'i'.'''' 'e'd'o'n'.'f'l'e's' 'f'i' '''' 'a'''&'''''Item':':'C'ig> Iterator for Nod''e''' 'a'''I'''''n ''' 'f'i' '''t''er<'a'n 'unimplemente'!'''''';')'('d''''''p'm'i'n'u' ','' ''C'''// '>'Self::Item''C::I''Node<C>'// '''C::I'''''''''''m'e't'I':':'f'l'e'// ''S'''''I':':'C' {n type Item = &'a Node<C>;nn fn next(&mut self) -> Opt'// 'ion<&'a No'// 'de<C>> {n let prev = self.0;n if let Some(n) = self.0 {n *self = NodeIter(unsafe { n.first_skip_entry().node.as_ref() });n }n prevn }n}'n'n'n'''// ''impl<C: ListConfig> Iterator for SkipList<C> {'// 'n type Item = C::Item;n'// 'n}''/'''n''''''''''''''' '''''''''r'o't'a'r'e't'I'l''' ''''''''''''''''Ite''''''''n ''''''''('t'x'e'n' 'n'f' 'n ' ';'m'''''m'e't'I':':'C' '=' 'm'e't'I' 'e'p'y't' '''}''n 'n ' 'p'm'i''n'n'''// ''''''''''ListCon''fi''n'''''n''n// impl<C: ListConfig> fmt::Debug for SkipList<C> {'''''''De''''''SkipLis'''''''// '''''n '''''''''''''''For''matter'''''m'r'o'F''''';'*'''''// '' '''debug_list(''''''''''''''.'// ''f'l'e'// ''s'('s'e'i'r't'n'e'.')''''''g'u'b'e'd'.'f' '''r'''''''''':':'t'm'f':':'d't's''o'F':':'t'm'f':':'d't's' 'e's'u' ''' '''''''''''''''''''''''Formatte'''''''''''''''''''' }''n 'n ' '{' 't'l'u's'e'R' '>'-' ')'>''''''_'''<'r''''''''''r'e't't'a'm'r'o'F' 't'u'm'&' ':'f' ','f'l'e's'&'('t'm'f' 'n'f''''n' '''}''n 'n ' '{' '>'C'<'t'''''l'i'k'S' 'r'o'f' 'bug':':'t'm'f''''''g'u'b'e'D' '>'g'''''t's'i'L' ':'C'<'l'p'm'i''''''' 'e'f'a's'''n'''''u''''''''n''''''''''''''''''l'o'o'b' ':'v'e'r'p'''''''''''''''''''n'e'r'r'u'c'_'y''' let item = if modify_prev { self.cursor.prev_item_mut() }' ''' let item ='' unsafe {n ';''' '' if'modify_prev'''''''''''''''self.cursor.prev_item_mut()''''y'f'i'd'o'm' self.i'self.cursor.current_item_mut('')'tem_offset > 0 { self.cursor.current_item'''''''''/'/' ';'0'_mut() }n else { self.cursor.prev_item_mut() }n }'''n ';'''n 'f'i'd'o'm''''item: &mut C::Item''''''''''''''''''''''''''''''''''''''''','m'e't'I':':'C' 't'u'm'&' ':'m'e''''''n '// ''let e'' = self.cursor.here_ptr()'''// ';' 't'i' ','>'C'<'e'd'o'' let old_usersize = C::get_usersize(item);n'''// ' modify_fn(item, se'('''lf.item_o')'''ffset);n ''le'// 't new_usersize = C::get_usersize(item'');nn'// ' let usersize_delta = new''_users'// 'ize as isize - old_usersize as isize;nn if usersize_'''' 'b'u'p'delta != 0 {n self.cursor.update_offsets(self.list.height(), usersize_delta);n self.list.num_usercount = self.list.num_usercount.wrapping_add(usersize_delta as usize);n self.'n 'unsafe { self.modify_item''''e'u'r't'(false, modify_fn); }' '''i''tem_''offs''et = usize::max(self.item_offset, new_usersize);n }nn (self.notify)(std::sl'self.cursor.here_ptr('');'''ice::from_ref(item),'' ItemMarker {n ptr: e,n // _phantom: PhantomData,n ''''''''''''''''''''''''' '&'&' '0' '>' 't'e's'f'f'o'_'m'e't'i'.'f'l'e's'(' });''n'N' 't'u'm'*' ':'')'e'''''n'*' ''''''n'prev_'''p''u''b'' ''struct Edit<'a, C: ListConfig, ''Notify: FnMut(&[C::Item]''' '''n '}''n 'n ''''''e's'l'a'f''' ''n fn modify_prev_item<F>(&mut self, modify_fn: F) where F: FnOnce(&mut C::Item, usize) {', ItemMarker<C>)> {n '''''n '''''''''''''prev_''''p''''''''''''''''''''''''''''' '// '''''''''''''.'r'o'n '''''''''item_offse''''''''''''''self.item_offse'''' '='''' '>' 't''''''''''current_item_mut(''}' ')'''''''r'r''''''' '{' '''e'''''' '''s'''''l'e''u'c'.''''n '''''''''''}'// '' '''''''x'e'n'.'r'o's'r'u'c'.''n ''''''''' '{' 'e'f'a's'n'u'''''''modify_item'''''''''''''current_item''}' '_mut()''''''''''n';''f'_'y'f'i'd'o'm'''''r'r'u'c'.'r'o's'r'u'c'.'f'l'e's'(item: &mut C::Item, modify_fn: F)''''''f'i'd'o'm'.'f'l'e's' 'f'l'e's' '{' '0' '>' 't'.'f'l'e's' 'f'i' ''n '''''' '''' ''s'r'u''''''''n '''''.'f'l'e's' '='=' ''c'''''''n ''''''!''modif' && self.cursor.is_at_n'prev_ite''''t'u'm'_'''m''()'''''v'e'r'p'ode_end()'y_n' ''''''''' '&'&' 'ex'''''''''''''''''''is_at_node_end('''''n ''' }'n '{' ')'''s'i'.'r'o's'r'u'c'.'f'l'e's' '&'&' 't'''''i'd'o'm' 'f'i' 'local_index'''''''_'l'a'c'o'l'.'f'l'e's' ''' }''n 'n ' '{' 'l'o'o'b' '>'-' ')'f'l'e's'&'('e'd'o'n'_'f'o'_'d'n''''d'''''''''''''f'o'_'n'e'_'t'a'''''''s'i' 'n'f' 'n ' 'list: &'a mut SkipList<C>,n cursor:'''''''''''''n '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''!'s't's'e't' 's'd'e'e'N' '.'t'c'e'r'r'o'c' 's'i' 'n'o'i't'c'n'u'f' 's'i'h't' 'f'i' 'e'r'u's' 't'o'N' ':'O'D'O'T' '/'/' '''''''''','l'o'o'b'''''t'x'e'n''''''''' ':'t'x'e'n'_'y'f'i'd'o'm''''''_'t'n'a'w' ' Cursor<C>,n 'n ''''''''''''''''is_at_node_end''n ''''''''get_usersize''''''''' '{' 'e'f'a's'n'u'''''(_it''}' 'em: &Self::Item)':'''''''''''''''''''''')'t'e's'f'f'o'_'m'e't'i''local_index'''''a'c'o'l'.'f'l'e's' '='<' ')'':'C'(''''''''''''current_ite'')'('m''''''''t'n'e'r'r'u'c'.'r'o's'r'u'c'*'''''''''.'f'l'e's'*' '|'|' '''''''|' ''''here_''here_pt'()'''r''()''''''_'e'r'e'h''''is_at_node_end('''n ''''''advance_item(''' 'n '''''.'f'l'e's''modif'''''''''''''''''''';')'n'f'''_'y'f'i'd'o'm' ','f'l'e's'('y_prev_item''''''''''''v'e'r'p'_'y'f'i'd'o'm' '}'n ';')'''''a'v'd'a'.'f'l'e's' '{' ')'.'r'o's'r'u'c'.'f'l'e's' 'f'i' ' item_offset: usiz'' }'n 'e, // Offset into the current item.'''''''''''' 'f'i' 'n notify: Notifyn}n// pub struct Edit<'a, C: ListConfig> {n// list: &'a mut SkipList<C>,n// c''' '// ' pub fn modify_prev_item<F>(&mut self, modify_fn: F) where F: FnOnce(&mut C::Item, usize) {n'''n '''n 'ursor: Cursor<C>,n// item_offset: usize, // Offset into the current item.n// notify: fn(&[C::Item]'prev_', ItemMarker<C>)n// }nn// impl<'a, C: ListConfig, N''otify: Fn' 'Mut(&[C::Item], ItemMarker<C>)> Edit<'a, C, Notify> {nimpl<'a, C: ListConfig, N: FnMut(&[C::Item], ItemMarker<C>)> Edit<'a, C, N> {n fn dbg_check_cursor_at(&self, userpos: usize, plus_items: usize) {n if cfg!(debug_assertio')'ns) {n l'('et (mut c2, _) = se't'lf.list.iter_at_use'h'rpos(userpos);n 'g' c2.advance_'i'by_items(plus_items'e', self.list.head.he'h'ight);n assert_eq!(&self.cursor, &c2);n }n }nn pub fn del(&mut self, num_items: usize) {n assert_eq!(self.item_offset, 0, 'Splitting nodes not yet supported');nn unsafe { self.list.del_at_ite'.'r(&self.cursor, num_items); }nn if cfg!(debug_assertions) {n let (c2, _) = self.list.iter_at_userpos(self.cursor.userpos);n if &self.cursor != &c2 { panic!('Invalid cursor after delete'); }n }n }nn pub fn insert_iter<I>(&mut self, mut contents: I) where I: ExactSizeIterator<Item=C::Item> {n if contents.len() == 0 { return; }n let num_inserted_items = contents.len();n n // userpos = min(userpos, self.get_userlen());n // let (mut cursor, offset) = self.iter_at_userpos(userpos);nn let start_userpos = self.cursor.userpos;nn unsafe {n if self.item_offset == 0 {n self.list.insert_at_iter(&mut self.cursor, &mut contents, &mut self.notify);nn self.dbg_check_cursor_at(start_userpos, num_inserted_items);n } else {n let current_item = self.cursor.current_item();n let (start, end) = C::split_item(current_item, self.item_offset);n // Move the cursor back to the start of the item we'ren // splitting.n self.cursor.move_to_item_start(self.list.head.height, self.item_offset);n // This feels pretty inefficient; but its probably fine.n self.list.replace_item(&mut self.cursor, start, &mut self.notify);nn // TODO: Consider concatenating end into contents then just calln // insert_at_iter once.n self.list.insert_at_iter(&mut self.cursor, &mut contents, &mut self.notify);nn self.dbg_check_cursor_at(start_userpos, num_inserted_items);nn self.list.insert_at_iter(&mut self.cursor, &mut iter::once(end), &mut self.notify);n }n }n }nn pub fn insert(&mut self, item: C::Item) {n self.insert_iter(iter::once(item));n }nn pub fn insert_slice(&mut self, items: &[C::Item]) where C::Item: Copy {n self.insert_iter(items.iter().copied());n }nn pub fn replace<I>(&mut self, removed_items: usize, mut inserted_content: I)n where I: ExactSizeIterator<Item=C::Item> {n assert_eq!(self.item_offset, 0, 'Splitting nodes not yet supported');nn let num_inserted_items = inserted_content.len();n let start_userpos = self.cursor.userpos;n n unsafe { self.list.replace_at_iter(&mut self.cursor, removed_items, &mut inserted_content, &mut self.notify); }nn self.dbg_check_cursor_at(start_userpos, num_inserted_items);n }nn pub fn prev_item(&self) -> Option<(&C::Item, usize)> {n if self.item_offset == 0 {n if self.cursor.local_index == 0 {n // The only time a cursor should be at the start of the node isn // when the cursor is at the start of the entire list.n assert!(self.cursor.userpos == 0, 'Invalid state: Cursor at start of node');n Nonen } else {n ')' let prev_i'('tem = unsafe { self.c't'ursor.prev_item() };n'h' Some('g'(prev_item, C::get_us'i'ersize(prev_item)))n 'e' }n 'h'} else {n Some((unsafe { self.cursor.current_item() }, self.item_offset))n }n }nn pub fn advance_item(&mut self) {n self.cursor.advance_item(self.list.head.height);n self.item_offset = 0;n }nn pub fn modify_i'.'tem<F>(&mut self, modify_fn: F) where F: FnOnce(&mut C::Item, usize) {n let e = self.cursor.here_ptr();n let item = unsafe { self.cursor.current_item_mut() };n let old_usersize = C::get_usersize(item);n modify_fn(item, self.item_offset);n let new_usersize = C::get_usersize(item);nn let usersize_delta = new_usersize as isize - old_usersize as isize;nn if usersize_delta != 0 {n self.cursor.update_offsets(self.list.head.height as usize, usersize_delta);n self.list.num_usercount = self.list.num_usercount.wrapping_add(usersize_delta as usize);n self.item_offset = usize::max(self.item_offset, new_usersize);n }nn (self.notify)(std::slice::from_ref(item), ItemMarker {n ptr: e,n // _phantom: PhantomData,n });n }nn pub fn replace_item(&mut self, replacement: C::Item) {n self.modify_item(|old, _offset| *old = replacement);n }n}n'n'n'n'n''':':'f'l'e'S'at<F>(&mu''''t'' self, ' self.edit(userpos, |edit| edit.del(num_items''''''); })'' self.edit(userpos, |edit| edit.del(num_items);'userpos: usize, modify_fn: F) wher''e F: FnOnce(&mut C::Item' self.edit(userpos,'''n ''' ''|edit| edit.modify_item(modify_fn'';')''''')''; }'' '''' self.''e''dit(u''serpos, |edit| edit.modify_item(modify_fn'');', usize'') 'n '''''''''''''''''''''''''st'_iter''''n '' '''''''''''''''''''''''''''''''''''''''')')'s't'n'e't'n'o'c'('t'r'e'''s'n'i'.'t'i'd'e' '|'t'i'd'e'|''''''''''''''''''modify_f'''' }'n ';')'n'''''''y'n ''''''edit_notify'''''''s'''''''y'f'i't'o'n'''o'p'r'e's'u'(userpos: usize, notify: fn(&[C::Item], ItemMarker<C>), f: F)''''i'd'e'.'f'l'e's' ''f'i'd'o''// 'm'('modify_item'''''i'd'o'm'.'t'i'd'e'''''''''''// ''e's' '{' 'art_userpo''''''''|'t'i'd'e'|' ','s''''''''u'_''// 't'r'a't's'('t'i'd'e'.'f'l'e's' '''{'''::from'// '_'''// 's'''// '''l'// 'ice(end_items), end_i''tems.len(), false, not''ify)'// ';n '// ' '// ' ''}n '// ' }n'' '// '// '' }nn // unsafe fn insert_at_iter(&mut sel'// 'f, cursor: ''&mut C'// 'urso'// 'r<C''>, c'// 'ontents: &[C::Item]) {n // '// 'self.insert_at_i''ter''_and'// '_''// '// 'notify(cur'// 'sor, contents'', S'// ''// 'elf::no_notify);n ''// }nn '// ' '// '/// Inter''estingly u'// 'nlike the original, here we only care '// '''about specif'// 'yin'// 'gn /// t''he number of r'// 'e''moved ite'// 'ms '// 'by counting the''m. We'// ' do not use'// ' usersize inn /// the deleted ''item count.n '// '// '' ///''n /// If the de'// 'leted content'' occurs at the start'// ' o'// 'f a node, the cursor passedn /// here must point to'' the end of t'// 'he previo'// 'us node, not the start of then /// current node.n unsafe fn d'// '''el_at_iter(&mu''t self, cu'// 'rsor: &'// 'mut '// 'Cursor<C>, mut num_deleted_i''tems: usize) {n ''if nu'// 'm_del'// 'eted_items == 0'// ' { ret''urn; }nn '' ''let'''// ' mut i'// 'tem_idx = cur''// '// 'sor.local_index;n let mut e = cursor.here_ptr();n ''''''''''' 't'u'm'&''n ''''''m'// 'odify_at'''''''// '''''''''// 's''''''''no_notif'''''''''''''''''''n 'assert_eq'''''''''''''''''''''''''''''''''''''''''''''''''''''''n '''''''' '='''' ' 'm'e't'i'*' ';')'''m'e't'i' 'e'r'i't'n'e' 'e'h't' 'y'f'i'd'o'm' 't's'u'm'''''''' 't'o'n'n'a'c' 't'a'_'e'c'a'l'p'e'r''' ','0' ','t'e's'f'f'o'('!''''s's'a''' }'n ' '{' '|'t'e's'f'f'o' ','m'e't'i'|'''''y''''(_items: &[C::Item], _marker: ItemMarker<C>)'''o'n''''N':':'f'l'e'S'o'p'r'e's'u'_'t'r'a't's'(us'n '''''''''''''''''unsafe { self.cursor.prev_item() ';'}' '=' 'm'e't'i'_'v'e'prev_item''''''_'v'e'r'p'''prev_item'''''v'e'r'p'r'p''' 't'e'l''self.cursor.prev_item()''' 'erpos: usize, mut notify: Notify, modify_fn: F)''''''f'i'd'''''get_usersize(_item: &Self::Item)':':'C'''o'm'.'f'l'e's' ' while num_deleted_items > 0 {n // self.print();n // if cfg!(debug_assertions) { self.check(); }n if item_idx == (*e).num_items as usize {n let entry = (*e).first_skip_entry();n // End of current node. Skip to'''// ' the start of the next one. We'ren '' // The only time a cursor'''''''''''e'''b' 'd'l'u'o'h's' is right at the start of the node isn // when the cursor is at the start of the entire list.'n ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'t's'i'l' 'e'r'i't'n'e' 'e'h''''n't' 'f'o' 't'r'a't's' 'e'h't' 't'a'''''h'g'i'r' 's'i''''s' 'r'o's'r'u'c' 'e'h't' 'n'e'h'w' 's'i' ''''''' ','e'd'o'n' 'e'h't'''''''o'n' 'f'o' 't'r'a't's' 'e'h't' 't'a' 't'h'g'i'r' 's'i' 'r'o's'r'u'c' 'a' 'e'm'i't' 'y'l'n'o' 'e'h'T'''''' '''' 'n'e'h'W'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''e'd'o'n' 't'x'e'n' 'e'h't' 'o't' 'e'v'o'm' 't'''n'o'd' 'e'd'''o'n' 'a' 'f'o' 'd'n'e' 'e'h't' 't'a'''''''''''''''''''''''''''e'd'o'n' 'a' 'f'o' 'd''''e'n'e' 'e'h't' 'o't' 'k'c'i't's'''''''' 'd'l'u'o'h's' 's'r'o's'r'u'C''''''''''''''''''''''''''''''''''''''''''''''''''' 'm'e't'i' 'e'h't' 'f'o' 'd'n'e' 'e'h't' 't'a' 'e'b' 's'y'a'w'l'a' 'd'l'u'o'h's' 's'r'o's'r'u'C' '/'/' ''''''n ''''C' '/'/' ' // intentionally not updating the it''''''''C''' ':'e't'a't's'erator'''''''''''''''''e'd'o'n' 'f'o' 't'r'a't's' 't'a' ' ''''''''''// '' ','y'f'i't'o'N'because if we del''e''ten '' ',''mut notify: Notif''y,' '''mut '// 'no'''''n 'n fn dbg_check_curso''r_at(&self, cursor: &Cursor<C>, userpos: usize, plus_items: usize) {n if cfg!(debug_assertions) {n '''''t's'i'l'.' let (mut c2, _) = self.iter_at_userpos(userpos);n '''''t's'i'l'.' c2.advance_by_items(pl'&''''''.'f'l'e's'us_items, self.head.height);n assert_eq!(cursor, &c2);n '''n '}n }' 'tify: Notify, ' // a whole no'n '' 'wher'// 'e Notify: FnMut(&[C::Item], ItemMarker<C>),'' ' '''''de we n'// 'eed the iterator to point to the previousn'' '// ' // element. And if we only delete here, the itera''tor doesn'tn'// ' '' /'// '/ need to be ''moved.n '// ' e = entry.node;n if e.is_null() { panic''!('Cannot delete p'// 'ast the end of the list'); }n item_idx = 0''''''' 't'u'm'''''''y'f''// '''i't'o'n'&';n '// ' }nn let e_num_items ''= (*e).num_items as usiz'// 'e;n let removed_here = min(num_dele''ted_ite''ms, e_num_items - i'// 'tem_idx);n n let heig''ht = (*e).height as usize;n '// ''' let removed_userlen'// ';nn if removed_here < e_nu''m_items || e as *const _ == &sel'// 'f.head as *const _ {n '''''.list'''n '' '' '''''''''needs_dro''''''''n '''''''''''''''''''''''''''''''''''Ite''''' ''''''insert_iter'''''''once''''m'';'e't'i'(value: T)'''n'o':':'r'e't'i'(mut contents: I)''''''r'e's'n'i'.'f'l'e's' ''' }''n 'n ' '{' ')'m''''e't'I':':'C' ':'m'e't'i' ','f'l'e's' 't'u'm'&'(''''('t'r'e's'n'i' 'n'f' 'b'u'p' 'n ' '''''''''>'''// ''{' '_iter' '' 'm'e't'''I':':'C'''''''>'T'<':':'p()''''e'e'n'// '':':'m'e'm'''''''''e'e'n':'' '' ':'r't'p'''' '''t'''u'''m'''''// ''''e'e'y'''f'n'i'''t'''o'''n'''''''':':'C''// ' ''' '&' }'n '' 'f'i' ''n ' '// ' ' pub fn prev_item(&self) -> Option<(&C::Item, usize)> {n if self.item_offset == 'n ''''''''''''''''local_inde'''''''{' '0' '='=' ' ''x''''''x'e'd'n'i'.'r'o's'r'u'c'.'f'l'e's' 'f'i' '0 {n ' ' '' '''''''{' 'e's'l'e' ' ''}'n ' assert!(self.cursor.userpos == 0, 'I'' }'' 'n 'Some((unsafe { self.cursor'current_ite''m''()'''''r'r'u'c'''''''e'n'.prev_item() }, self.item_offset))' ' '' }'n 'nvalid cursor');n No''nen } else' Some((unsafe { self.cursor.prev_item() }, self.item_offset)'n } else {')n' {n Some((unsafe { self.cursor.current_item() }, self.item_offset))n }n }nn pub fn advance_item(&mut self) {n' ' ''''''''m'e't'i' ''''i'''''''''''''''''''''''''''' 't'' 'u'm't''n 'u' '// ' 'm' 'y' 'f' 'i'''''t'''''''o'dro'n'''p_in_plac''e'''''.list'''(to_d''ro''p: *'''';')'mut T'// ')'''''&'p'r'd''// ':':'r't'p'''// '''''''''''''''''''''''''''p'o'r'd':':'m'e'm' ''' '''t'''''''u'as_mu'm't_pt'')'('r'y'''''_'''''''<'n'o'i't'p'O'''''>''n '''''''''''''''''''''''''''''''''''''item_offse'''''''''''''''' else {'''''('e'm'o'S' (unsafe { self.cursor.current_item() }, self.i'''}' ')'tem_offset)'n ''''''' '{' 'e's'l'e' '}' 'e'n'o'N' '{' '0' '='=' 't''''e't'i'.'f'l'e's' '&'&''''7' '0' '='=' 's'o'p'r'e's'u'.'r'o's'r'u'c'.'f'l'e's' 'f'i' '''i'u't'o'I''f''s'a''i'.'m'e't''t'i''o' '' '// ' 'n ' ''p''u''b'' ''f''n'' edit_notify<Notify,'' F, R>(&mut sel'// 'f, userpos: usize, notify: Notify, f: F) -> Rn where Notify: FnMut(&[C::Item], ItemMa'''// ''''// '''rker<C>'')'','''''''''''{no_notify_x::<C>}''expected type, found function''{''''''''''('f'o'}''''e'p'y't'''')''<''n'''''::<C''' as FnMut(&[C::Item], ItemMarker<C>)'''>''''''''''''''''''''''''''FnMut(&[C::Item], ItemMarker<C'''>'>)' 's'a' '>'C'<':':'x'_'y'f'i't'o'n'_'''ot''no_notify_x(_items: &[C::Item], _marker: ItemMarker<C>)'''// ''''// '''''t'o'n' ',' ''F: F''''N'N' ','nOnce(&mut Edit''<C'// ', Notify' ''wh''n'f'ere ''nn pub fn insert(&mut self, item: C::Item) ''{n self.insert_iter(iter::on'.list'ce(item));n '''' }'// 'F: Fn''On'// 'ce('''''' 'n'y'd'''''''''FnMut(&[C::Item], ItemMark''er<C'// '>)' 'l'', Notif'// 'y'''p'm'i'''&mut'// ' Edit''''',''n '' NN'':'' FnMut(&[C''::Item''// '// '], ItemMark''er<C>)'// ' '''' '''<C, NN>) -> R,n '' NN:'' impl FnM'''// 'ut(&[C::'// 'Item], ''ItemMark'// 'er<C>) {'' whe''re F'''n '''''''''''''''''''''''''''''''''''''' ':'s'm'e'''''''''''''''''''''''''' ''''''''''''_iter''''''''''''''''''''''''';')')'('d'e'i'''''''i'e'p'o''''l'c'.')'('r'e't'i'.'s'm'e't'i'('t'r'e's'n'i'.'f'l'e's' ''' }''n 'n ' '{' 'y'p'o'C' ':'m'e't''''m'I':':'C' 'e'r'e'h'w' ')'t'i''''''''''']'m'e't'I':':'C'['&' ','f'l'e's' 't'u'm'&'('e'c'i'l's'_'t'r'e's'n'i' 'n'f' 'b'u'p' 'n ' ''// ': FnOnce(&m''ut Edit''<'// 'C, N''N>) -> R, '// 'NN: impl ''FnMu''''t(&['// 'C' // pub fn ''edit_notify<Notify, F, R''>(&mut self, userp''os: usize, notify: ''' pub fn insert<I>(&mut self, mut contents: I) where I: ExactSizeIterator<Item=C::Item> {'' ''n ' pu''''b fn inse','''rt_at<Notify'', I>(&mut ''self, mut userpos: usize, mut contents'' '// ' userpos = min(userpos, self.get_userlen());n '// ' let (mut cursor, offset) = self.iter_at_userpos(user'''n '''''''''''''''''s'o'p'r'e's'u'_'t'r'a't's''''''''''''''''''''''''''''''''''''''';'s'o'p'r'e's'u'.'r'o's'r'u'c'.'f'l'e's' '=' 's'o'p'r'e's'u'_'l''''_'a'i't'i'n'i' 't'e'l' 'n ' 'pos);n'n''':'' I, mut notify: Noti''''''item_offset''''''_'m'e't'i'.'start_userpos''f'l'e's'fy'''''.'t's'i'l')n wher'''''.'f'l'e's'e Notify: FnM''mut '''&mut'''''.'f'l'e's' '''u''t(&['''''n ''''''''''''''''''''''''' 't'u'm'''''''''''''''''''''''''''''''''n ''' ''''''modify_item'''''''_'''''''t''''{'e's'f'f'o' ','''''''''''''''''''''t';''n'e'm'e'c'a'l'p'e'r' '=' 'd'l'o'*' '|'d'l'o''''e'|'''(modify_fn: F)'''''i'd'o'm'.'f'l'e's' ''' }''n 'n ' '{' ')'m'e't'I':':'C' ':'t'n'e'm'e'c'a'l'p'e'r' ','f'l'e's'&'('m'e't'i'_'e'c'a'l'p'e'r' 'n'f' 'b'u'p' 'n ' ''''.'f'l'e's'C'''''t's'i'l'.'::Item], Ite'''''.'f'l'e's'mMarker'self''''m'e't'i''''''''''''local_offset'.loca''offset'''''''loca''local_offset'''''a'c'o'l'.'f'l'e's'<C>), I: ExactSizeIterator<Item=C:'''''.'f'l'e's':Item> {n if '''''t's'i'l'.'cont'self.item_offset'ents.len() == 0 { return; }n let num_inserted_items = contents.len();n n '''''t's'i'l'.'userpos ''''''.'f'l'e's''''''e's'='''''.'f'l'e's' min(userpos, self.get_userlen());n let (mut cursor, offset) = self.iter_at_userpos(userpos);nn unsafe {n if offset '''''t's'i'l'.'== 0 {n '''''.'f'l'e's' self.i'''''.'f'l'e's'nsert_at_iter(&mut cu'''''.'t's'i'l'rsor, &mut '''''.'f'l'e''start_userpos'''''r'a't's''userpos'''''r'a't's's'contents'''''.'t's'i'l', &mut not'''''.'f'l'e's'ify);nn se'''''.'f'l'e's'lf.dbg_check_cursor_at(&cursor, userpos, num_inserted_items);n } else {n let current_item = cursor.current_item();n let (start, end) = C::split_item(current_item, offset);n // Move the cursor back to the start of the item we'ren // splitting.n cursor.move_to_item_start(self.head.height, offset);n // This feels pretty inefficient; but its probably fine.n self.replace_item(&mut cursor, start, &mut notify);nn // TODO: Consider concatenating end into contents then just calln // insert_at_iter once.n self.insert_at_iter(&mut cursor, &mut contents, &mut notify);nn self.dbg_check_cursor_at(&cursor, userpos, num_inserted_items);nn self.insert_at_iter(&mut cursor, &mut iter::once(end), &mut notify);n }n }nn }' 'n ' 'Notify, f: F) -> Rn //'' where Notify: FnMut(&[C::Item], ItemMarker<C>), F: FnOnce(&mut Edit<C'', Notify>) -> R {n // let (cursor, item_offset) = self.iter_at_userpos''(userpos);n // let mut edit = Edit { list: self, cur''sor, item_offset, notify'' };nn // // TODO: Or maybe I sho'''''n 'n ' 'uld p'// 'ass ownership here?n // f(&mut edit)n // }n'::''Ite'// 'm], ItemM'Notify, '''arker<C>) {'>) -> R {''n''/'// '/ ' '''&'''fn(&[C::Item], ItemMarker<C>)''// 'c''// 'n'''['// 'item_idx''..''''''it'Notif''''n'f'y: FnMut(&[C::It'// 'em], ItemMarker<C>), '''''N''''//'' ''''''// ''FnMut(&[C::Item], ItemMarke'// 'r<C>)' 'l'p'm'''i''''''''for<'r> fn(&'r [<C as'' skiplis'// ''''// 't::ListConfig>'// '::Item],'' skiplist::ItemMarker<C>) ''{skiplist::no_''notify_x::<C>}'>'''''''R''// 'n '// ''N' 'for<'r>'''' fn(&'r [<C ''''as Li'//'' 'stConfig>::Item], '// 'ItemMarker<C>) {''''''&' '''''''''' '}''''>'// ''-' '''''' ''':'N' ',''')'N'''e'// 'm_idx +'&''for<'r> fn(&'r [<C ''as'' skipl'// 'ist:'':Li'// 'stConfig>::It''e''m'''// ']'',''''''''{no_notify_x::<C>}' ' skiplist::ItemMar''ker<C>'')'' '// '{skiplist::no_notify_x::<C>}''''2'3'''''''''3'2'u''''// '''// 'C'''''''>'_''' removed_h'// 'e'''''''''>'C'<':':'r'' 'n ' let (cursor, item_offset) = self.iter_at_userpos('&'userpos);n '' let mut edit = Edit { ''list: self, cu'''''''' ':'y'f'i't'o'n''no_notify_'':':''''>'C'<'''x'''<'(_items: &[C::It''em'>'], _m'// 'arker: ItemMarker<C>)''''''o'n'_'o'n'rsor, 'FnMut'''n'f'item_offset, notify'''''// ''''n'''n'''''''''''''''':':'''''// '>'C'<'x'_'y'f'i't'o'n'_'// '''''n'o''no_notify_x(_items: &[C::Item], _marker: ItemMar'// 'ker<C>)'''o'n''' ':' '// '};nn // TODO: Or maybe ''I should pass ownership here?n '' f(&mut edit)n' '''e'''''''// '// '''' '''''''''''' ','y'f'i't'o'N' ''''''''''''''y'f''' ''''''''''''''''''''''''''''''''&'('''''''''''''''' '(''''''// ''''''.'f'l'e's'''''''unsaf''''''''item_offse''''n ''''''''''''''''''''''''''f'''' '''''''''''''advance_item''''''lis''''''''''''t''n ''''''item_offse''''';'0' '''' pub fn modif'''''m'e't'i'_'y<F>(&mut self,'' userpos: usize, modify_fn: F) where F: FnOnce(&mut C::Item, usize) {''''''''n 'n '''''.'f'l'e's' pub fn modif''''y'''''''''_'n'i''''''''''.'f'l'e's'''''''''''m'e't'i'''_''''at<Notify, F>(&mut self, userpos: usize, mut notify: Notify, modify_''''''item_offse''t'.'f'l'e's'fn: F)n '''''n ''''new_usersiz'''''''''item_offset''''e't'i'.'f'l'e's' '>' 'e'''''_'w'e'n''''(' 'f'i' ' where Notify: FnMut(&[C::Item], ItemMarker<C>), F: FnOnce(&mut C::Item, usize) {n let (mut cursor, offset) = self.iter_at_userpos(userpos);n '''''.'f'l'e's' let e = curso'''''.'t's'i'l'''''n ''''''item_offse''''''''''''''''('x'a'm':':'e''''new_usersiz'';''')'e' ','z'i's'u' ''''''''item_offse'''''''a'm'.'t''i'.'f'l'e's' '=' 't'''''m'e't'i'.'f'l'e's' ''n if new_usersize > self.item_offset {n self.item_offset = new_usersize'''''''''''' '/'/' ';n }''''' ''n ' if new_user'''' ''''''item_offse''''new_usersiz';'e''''''u'_'w'e'n' '=' 't''''''_'m'e't'i'.'f'l'e's' ''' }''n 'n ' '{' 'size > self.item_offset' 'n ' 'r.here_ptr();n let item = unsafe { curs'''''.'t's'i'l'or.current_'''''.'t's'i'l'item_mut() };n let old_usersize = C::get_usersize(item)'(''''''.'f'l'')'e's';n modify_fn(item, offset);n let new_usersize = C::get_usersiz''e(item);nn let usersize_delta = new_usersize as isize - old_usersize as isize;nn if usersize_delta != 0 {n cursor.update_offsets(self.head.height as usize, usersize_delta);n self.num_usercount = self.num_usercount.wrapping_add(usersize_delta as usize);n }nn notify(std::slice::from_ref(item), ItemMarker {n ptr: e,n // _phantom: PhantomData,n });nn // cursor.update_offsets(self.head.height as usize, new_size as isize - old_size as isize);n }''''unsafe { cursor.current_item_mut() };' 'n ' '=' 't'''''''''f'f'o'_'m'e't'i'.'f'l'e's' ';''h'g'i'e'h'.'d'a'e'h'.'t'.'f'l'e's'(height: u8)''''''n'a'v'd'a'.'r'o's'r'u'c'.'f'l'e's' ''' }''n 'n ' '{' ''l'e's' 't'u'm'&'')'('m'e't'i'_'t'x'e'n' 'n'f' 'b'u'p' 'n ' ')'t'''''''''f'f'o'_'m'e't'i'.'f'l'e's' ','e { curs''o''''r''.''current_item_mut() };''''''''.'r'o's'r'u'c'.'f'l'e's' ''' }''n 'n ' '{' ')'e'z'i's'u' ',''Item'''''m'e't'I':':'C' '>'-' '''''' ','f'l'e's'&'')'('m'e't'i'_'t'n'e'r'r'u'c' 'n'f' 'b'u'p' '''''''n 'n ' ':':''''>'C'<''''''// ''''''''''>'C'<'x'_'i't'''o'N' ',''' '/'''Notify: ''''no_''notify_'''''>'C'<'''x''''''_items: &[C::Item'']'''>'C'<'(_item''s: &[C::Item'>'], _mar''ker: '// 'ItemMarker<C>)''''''o'n'_'o'n''Self::'// 'no_notify''rustc --explain E057'// '3'<''SkipLi't'''''''''''// ''Ski''Sk'// pub struct Edit<'a, C: ListConfig, Notify: Fn'// '''' n''otify: fn(&[C::Item], ItemMarker<C'// '>)n'Mu'''// ''''// 't(&[C::Item], ItemMarker<C>)> {n'// '// list: &'a mut SkipList<C>,n// cursor: Cursor<C>,n// item_offset: usize, // Offset into the current item.n// notify: Notifyn// }''n''// 'ipLis'''''>'C'<'t''''i'k''', Notify: FnMut(&[C::Item], ItemMarker<C>)''''S' 's'a' ''>''''s'''''''''>'C'<':':'t'''''l'i'k'S''''''''// 'FnMut(&[C::I'type''n'f'', Notify: FnMut(&'''// '[C::Item]'// ','' ItemMarker<C>)' Self::n''o_noti'// 'fy'tem], ItemMa''rke''r<C>)'/'nimpl<'a, C: ListConfig, Notify: FnMut(&[C::Item], ItemMarker<C>)> Edit<'a, C> {'/ ', '/ ' '' }'n 'n 'nimpl<'a, C: Li'''n n pub fn replace_at<I>(&mut'' self, mut start_userpos: usize, removed_ite'n '''ms: usize, mut inserted_content: I) whe''''re I: ExactSize''''''''''_'m'e't'i'.'f'l'e's'Iterator<Item=C::Item> {n start_userpos = min(start_userpos, self.get_userlen()'n '''''''''''''''''''''''''' ''curso''userpo''''n ';'s'''''r'e's'u''''''r'u'c'.'r'''''s'r'u'c'.'f'l'e's' '=' 's'o'p'r'e's'u'_'t'r'a't's' 't'e'l' ');nn let (mut c'''''t's'i'l'.'ursor, offse'''''.'f'l'e's't) = self.iter_at_userpos(start_userpos);n '''''''''''y'f''''/'''''t's'i'l'.'/ 'i't'o'n'.'''''.'f'l'e''start_userpos''''''.'f'l'e's's''f'l'e's''' assert_eq!(offset, 0, 'Splitting nodes not yet supported');nn let num_inserted_items = inserted_content.len();n unsafe { self.replace_at_iter(&mut cursor, removed_items, &mut inserted_content, Self::no_notify); }nn self.dbg_check_cursor_at(&cursor, start_userpos, num_inserted_items);n }'stConfig, Notify: FnMut(&[C::Item], ItemMarker<C>)> Edit<'a'', C, Notify> {' '// '''''''y'f'i't'o'N' pu''b fn del_a'// 't(&mu''''t '// 'self,'// ' mut use''''''' 'e'p'y't''Self::no_notify''''impl''''''''o'''' ''''o'e'p'y't'''''''''''''l'p'm'i''''''''''''''''''y'f'i't'o'n'_'o'n''''no_notify(_items: &[C::Item], _marker: ItemMarker<C>)':':'f'l'e'S''''_' ','rpos: usi'n ''''''edit_notify'''''''s''''''''no_notif'''f' ','''''n ''y(_items: &[C::Item], _marker: ItemMarker<C>)':':'f'l'e'S'o'p'r'e's'u'(userpos: usize, notify: Notify, f: F)'''''t'i'd'e'.'f'l'e's' ''' }'n 'ze, n''''''''y'f'i't'o'N' ','um_items:'n pub fn'''''''y'f'item_''i't'o'n'_''''''''''o'n')' '''''''' ','' let mut edit = Edit { list: self, cursor, item_offset, notify };'' let mut edit = Edit { list: self, cursor, item_offset, notify'y'f'i't'o'N'edit<F, R>(&mut se' list: self, cursor, item_offset, notify'' list: self, cursor, item_offset,'' list: self, cursor,'lf, userpos: u'''''''''''''''''where Notify:'' FnMut(&[C::Item], It''emMa'item_'rker<C>'' ',''''''n ''''''y'f'i't'o'n' ',' ')','y'f'i't'o'N' ':'y'f'i't'o'n' 'size, f: F) -> Rn where F: FnOnce(&mut Edit<C>) -> R {' usize) {n '// ' userpos = min(userpos, self.get_userlen());n '// ' // We can't easily trim num_items.n '// ' '''n ''''''''''n 'n pub fn replace_at<I>(&mut self, mut start_userpos: usize, removed_items: usize, mut inserted_content: I) where I: ExactSizeIterator<Item=C::Item> {n start_userpos = min(start_userpos, self.get_userlen());nn let (mut cursor, offset) = self.iter_at_userpos(start_userpos);n assert_eq!(offset, 0, 'Splitting nodes not yet supported');nn let num_inserted_items = inserted_content.len();n unsafe { self.replace_at_iter(&mut cursor, removed_items, &mut inserted_content, Self::no_notify); }nn self.dbg_check_cursor_at(&cursor, start_userpos, num_inserted_items);n }' 'n ' ' // num_items = min(length, self.num_chars() - pos);n '// ' if num_items == 0 { return; }nn '// ' let (mut cursor, offset) = self.iter_at_userpos(userpos);n '// ' assert_eq!(offset, 0, 'Splitting nodes not yet supported');nn '// ' unsafe { self.del_at_iter(&mut cursor, num_items); }nn '// ' if cfg!(debug_assertions) {n '// ' let (c2, _) = self.iter_at_userpos(userpos);n '// ' if &cursor != &c2 { panic!('Invalid cursor after dele'''n 'pub fn del_at(&mut self,'''' mut userpos: usize, num_items: usize'''' ''''''''''''''''''''''''''''' ''''''''''''''''''''''';')'s'm'e't'i'_'m'u'n'('t'a'_'l'e'd'.'t'i'd'e' ''' ')'}''n 'n ' '{' '|'t'i'd'e'|' ','s'o'p'r'e's'u'('t'i'd'e'.'f'l'e's' ''' }''n 'n ' '{' ')' 'n ' 'te'); }n '// ' }n '// ' }n''' '&' '{''''''where'' Notify: FnMut(&[C::I'''Notify: FnMut(&[C::Item], ItemMarker<C>)''''''''''''Notify: FnMut(&[C::Item], ItemMarker<C>)' ':'y'f'i't'o'N' ','tem], ItemMarker<C>)' ''']'n')' 'n'i' 'm'n '''''''' ':'y'''f'''i't'o'n''''''''' ':''''Notify: FnMut(&[C::Item], ItemMarker<C>)' ','y'f'i'''''''''y'f'i't'o'N' ','t'o'N' ''e't'i' 't'u'm'&' 'r'o'f' '''''n 'n ' ' // Just trim the node down.n let trailing_items = e_num_items - item_idx - r'''''''''no_not'item'if''''y''''''''''''''''''(_items: &[C::Item], _marker: ItemMarker<C>)'''o'n':':'f'l'e'S' ','emoved_here;n n let c = &mut (*e).items;n removed_userlen = C::userlen_of_slice(maybeinit_slice_get_ref(&c[item_idx..item_idx + removed_here]));n if trailing_items > 0 {n ptr::copy(n &c[item_idx + removed_here],n '''n ''''''''''''''' ','F'''>'R'<'''''''''''''''','e'z'i's'u' ':'s'o'p'r'e's'u' ''''''F' ':''n'''''R' '>'-' ' 'n '''''''''''''''''''''''''''''iter_at_userpos'''''''s';'''''''' 't'u'm' ''o'p'r'e's'u'(target_userpos: usize)''''''_'r'e't'i'.'f'l'e's' '=' ')''''''''n 'local_of'n '''''''''''''''''''''''''''''''''''''''''''''''?'e'r'e'h' 'p'i'h's'r'e'n'w'o' 's's'a'p' 'd'l'u'o'h's' 'I' 'e'b'y'a'm' 'r'O' ':'O'D'O'T' '/'/' 'fse''''''''t'e's'f'f'''''n ''''''' 't'u'm'&''''*'''''')'t'i'd'e'('f' 'n ' ';'o' ':'t''''''l'a'c'o'l' ','r'o's'r'u'c''t'e's'f'f'o' ','r'o's'r'u'c'(' 't'e'l' ' ' ''''''''''''''''''n ''''''''''''n ''''''''''''''''''''r'u'c'.'f'l'e's'''''''c'.'s'i'h't'''''s'r'u'c' ':'r'o's'r'u'c' ','f'l'e's' ':'t's'i'l' ''' }'n 'item' '{' 't'i'd'E' '=' 't'i'd'e' 't'e'l' '''''''''''FnOnc'''''' 't'u'm''''''' '' '' '''n '' 'n // if cfg!(debug_asserti''ons) {n // ''''''''.'t's'i'l'.' let (c2, _) = ''''''''''''.'r'o's'r'u'''''.'f'l'e's''c'.'f'l'e's'self.iter_at_userpos(use''rpos);n // '' if &cursor != &c2 { panic!('Invalid cursor after delet''e'); }n // }' '''' }''n 'n pub fn del_at(&mut sel''f, mut userpos: usiz' assert_eq!''''''item'''''''_'l'a'c'o'l'.'f'l'e's'(offset, 0, 'Splitting nodes'''''t's'i'l'.' not'''' yet''''''''''''n '''''''''''''''''''''''''''''''''''''''''?'d'i'l'a'v' 'l'l'i't's' 's'i' 'r'o's'r'u'c' 'e'h't' 'k'c'e'h'C' ':'O'D'O'T' '/'/' 'n ' '''r'''o'''s'r'u'c'.'f'l'e's' su'// 'pported');n'''''''e, num_items: usiz'// 'e) {n userp'''''''''t's'i'l'.'f'l'e's'userpos''''''.'f''// 'l'e's''os = min(userpos, self.get_userlen());n // We can't easily '// 'trim num_items.n // num_items = min(length, self.num_chars() - pos);n if num_items == 0 { return; }nn let (mut cursor, offset) = self.iter_at_userpos(userpos);n assert_eq!(offset, 0, 'Splitting nodes not yet supported');nn unsafe { self.del_at_iter(&mut cursor, num_items); }nn if cfg!(debug_assertions) {n let (c2, _) = self.iter_at_userpos(userpos);n if &cursor != &c2 { panic!('Invalid cursor after delete'); }n }n }n' 'n ' '{' '&''''''''n pub fn del_at(&mut self, mut userpos: usize, num_items: usize) {n userpos = min(userpos, self.get_userlen());n // We can't easily trim num_items.n // num_items = min(length, self.num_chars() - pos);n if num_items == 0 { return; }nn let (mut cursor, offset) = self.iter_at_userpos(userpos);n assert_eq!(offset, 0, 'Splitting nodes not yet supported');nn unsafe { self.del_at_iter(&mut cursor, num_items); }nn if cfg!(debug_assertions) {n let (c2, _) = self.iter_at_userpos(userpos);n if &cursor != &c2 { panic!('Invalid cursor after delete'); }n }n }n''''')'>'C'<'t'i'd'E'('e'''''n'O'n'F' ':'F' 'e'r'e'h'w' '''' 'f'''''''''''''R' '>'-' '''''' ','')'f'l'e's' 't'u'm'&'('t'i'd'''''''d'i'e' 'n'f' 'b'u'p' 'n ' ' &mut c[item_idx],n trailing_items);n }nn (*e).num_items -= removed_here as u8;n self.num_items -= removed_here;n self.num_usercount -= removed_userlen;nn for s in (*e).nexts_mut() {n s.skip_usersize -= removed_userlen;n }n } else {n // Remove the node from the skip list entirely. e should be then // next node after the position of the iterator.n assert_ne!(cursor.here_ptr(), e);nn removed_userlen = (*e).get_userlen();n let next = (*e).first_skip_entry().node;nn // println!('removing {:?} contents {:?} height {}', e, (''''' 'b'u'p'''''''''''''ListConfig''''s'i'L' ':'C' ',''>'a'''<''''''n '''''''''Curso'''''n '''''''''''''''''''''''''''''''''''''''''''''''''''''.'m''''''''''''''ListConfi'>'g''''''''''''''}''n 'n ' '{' '>'C' ','a'''<''''t's'i'L' ':'C' ','a'''<''''''t'i'd'E' 'l'p'm'i'e't'i' 't'n'e'r'r'u'c' 'e'h't' 'o't'n'i' 't'e's'f'f'O' '/'/' ','e'z'i's'u' ':'t'e's'f'f'o'_'l'a'c'o'l' ','>'C'<'r''''r'u'C' ':'r'o's'r'u'c' ','>'C'<''''' ''' 'a''SkipList'''''l'i'k'S'''''T'D'R'C''' ''''''''''' 't'u'm'&' ':'t's'i'l''''&' '''}''n 'n ' '{''''''''' 't'i'd'E' 't'c'u'r't's'''''n'n'n'n'n'*e).content_slice(), height);nn for i in 0..height {n let s = &mut (*cursor.entries[i].node).nexts_mut()[i];n s.node = (*e).nexts_mut()[i].node;n s.skip_usersize += (*e).nexts()[i].skip_usersize - removed_userlen;n }nn self.num_items -= (*e).num_items as usize;n self.num_usercount -= removed_userlen;nn // Update parents.n if height > 1 {n let mut n = e;n // let new_parent = cursor.entries[height - 1].node;nn // If you imagine this node as a big building, we need ton // update the parent of all the nodes we cast a shadow over.n // So, if our height is 3 and the next nodes have heights 1n // and 2, they both need new parents.n let mut parent_height = 1;n let cursor_node = cursor.here_ptr();n let cursor_node_height = (*cursor_node).height as usize;n let mut new_parent = if height >= cursor_node_height {n cursor.entries[parent_height].noden } else {n cursor_noden };nn loop {n n = (*n).nexts_mut()[parent_height - 1].node;n if n.is_null() || (*n).height >= height as u8 { break; }n let n_height = (*n).height as usize;n n assert_eq!((*n).parent, e);n assert!(n_height >= parent_height - 1);nn if n_height > parent_height {n parent_height = n_height;n if n_height >= cursor_node_height {n new_parent = cursor.entries[parent_height].noden }n }n n (*n).parent = new_parent;n }n }nn Node::free(e);n e = next;n }nn for i in height..self.head.height as usize {n let s = &mut (*cursor.entries[i].node).nexts_mut()[i];n s.skip_usersize -= removed_userlen;n }nn num_deleted_items -= removed_here;nn // if cfg!(debug_assertions) { self.check(); }n }n }nnn unsafe fn replace_at_iter<Notify, I>(&mut self, cursor: &mut Cursor<C>, mut removed_items: usize, inserted_content: &mut I, mut notify: Notify)n where Notify: FnMut(&[C::Item], ItemMarker<C>), I: ExactSizeIterator<Item=C::Item> {n i';'''f'' removed_items' ''' == 0 && inserted_content.len() == 0 { return; }nn '' // Replace '''' 'b'u'p'as' 'n self.num_usercount = self.num_usercount.wrapping_add(usersize_delta as usize);' ' many items from 'n 'n }' }'removed_items as we can with i'n // I hate this.'nserted_content.n let mut replaced_items = min(removed_items, inserted_content.len());n removed_items -= replaced_items;nn while replaced_items > 0 {n debug_assert!(inserted_content.len() >= replaced_items);n let mut e = cursor.here_ptr();n if cursor.local_index == (*e).num_items as usize {n // Move to the next item.n e = cursor.advance_node();n if e.is_null() { panic!('Cannot replace past the end of the list'); }n }nn let index = cursor.local_index;nn let e_num_items = (*e).num_items as usize;n let replaced_items_here = min(replaced_items, e_num_items - index);nn let dest = &mut (*e).items[index..index + replaced_items_here];n let old_usersize = C::userlen_of_slice(maybeinit_slice_get_ref(dest));nn // Replace the items themselves. Everything else is commentary.n // Would prefer to use zip() but it wants ownership of inserted_content :/n for slot in dest.iter_mut() {n *slot.as_mut_ptr() = inserted_content.next().unwrap();n }nn let dest = maybeinit_slice_get_ref(dest);n let new_usersize = C::userlen_of_slice(dest);n '' let use''' unsafe fn replace_item<Notify>(&mut self, cursor: &mut Cur'''// ''''// 'sor<C>, new_item: C::Item,'' mut notify: Notify)' 'n where Notify: FnMut(&[C::Item], ItemM'n '''''''''''''''n notify(std::slice::from_ref(item), ItemMarker {n ptr: e,n _phantom: PhantomData,n });n'''''''y'l'i's'a'e' '''''''''''''''.'d'e'z'i'm'i't'p'o' 'e'b' 'd'l'u'o'c' 's'i'h'T' '/'/' ''n '' ''''''replace_at_iter''''''r''1'''''' 't'u'm'&''''''''''''''''''''''')'''''''''''y';''f'i't'o'n'm'e't'i'_'w'e'n'('e'c'n'o':':'r'e't'i'''''e'c'n'o'o's'r'u'c'(cursor: &mut Cursor<C>, mut removed_items: usize, inserted_content: &mut I, mut notify: Notify)''''''a'l'p'e'r'.'f'l'e's' 'arker<C>) {'' unsafe fn replace_item<Notify>(&mut self, cursor: &mut Cursor<C>, new_item: C::Item, mut notify: Notify) where Notify: FnMut(&[C::Item], ItemMarker<C>) {'' ''n ' unsafe ''''m'e't'i'''''f''n'' ''r''e''p''lace_at_iter'''''''''''''''''''m'e't'I':':'C' ':'m'e't'i'_'''''''''''''m'e't'I'w'e'n' ','''<Notify, I>(&mut s'' 'n ''' ' '''' ' ' 'elf, cursor: &mut Curs' '' '''or<C>, mut ' ' '''n ' ' ' ' 'removed_ite'''' '''''' ','y'' 'f'i't'o'''''''t'i'N'm'', mut notify: Notif'' '' ''y'''''''''N' ','' where Noti' 'fy: FnMut(&[C::Item], ItemMarker<C>)'', where F' ': FnOnce(&mut'' C::Item'n if usersize_delta != 0 {', ' 'u' 'size) {'''s: usize, inserted_content: &mu'n cursor.update_offsets(self.head.height as usize, usersize_delta);'t I, mut n', mu' 't ','''no''tify: Not' 'ify)' 'n self.num_usercount = self.num_usercount.wrapping_add(usersize_delta as usize);' 'n where Notify' ': FnMut(&[C'n }'::''Item], ItemMarker<C>)'otify: ''''''''''''''''_' 't'u'm'*' 's'a' 'N' 'n let item = unsafe { cursor.current_item_mut() };' 'otify)' 'n '' where'''n '''''''''''''std::slice::from_ref(item';')' '=' 'e'c'i'l's' 't'e'l' ' Notify: FnMut(&'n let old_usersize = C::get_usersize(item);''''' '' }'n '''n modify_fn(item, offset);''[C::Item], ItemMa' ''let e = cursor.here_ptr'n let new_usersize = C::get_usersize(item);''''n '();''''{'rker<''C>), 'std::slice::from_ref(item)''''''e'c'i'l's'I: ExactSizeIterator<Item=C::Item> {n' 'n ' 'rsize_''delta ='// ' new_usersi''ze as isize - old_usersize as isize;nn'' '// ' if usersize_del'// 'ta != 0 {n cursor.up'// 'date_offsets(se' '''''''''''''''''''{' 'e'f'a's'n'u' '''''''''''}' ''current_ite''m''_''''r'e's'u'm''u'n ''''''''''''''''''here_ptr(';')'''''e'r'e'h'.'r'o's'r'u'c' '=' 'e' 't'e'l' 't(''''n'}' ''''''''''e'''''':':'d't's'''''''''''''''''('f'')'''e'r'_'m'o'r'f':':'''''''''here_ptr()'''''e'r'e'h'.'r'o's'r'u'c'''e'c'i'l's''''''''''o't'n'i''''''')'('m'o'r'f'.'m'e't'i'''''''['&''''''''' 'modify_fn'''''''y'f'i'd'' ''''''r'''e'''s'''u'''''''''C::get_usersize(item)'''n ''n 'let usersize_delta = new_usersize as i''si' ' '''''' '''n 'n notify(dest, It' 'emMarker {n ' ' ptr: e,n _phantom: Ph' 'antomData,n });' 'n ' '''' ''n 'n ' 'ze - old_usersize as isize;nn ' ' if usersize_delta != 0 {n ';'c''ursor.upd''a''te_offsets(self.head.heig' 'ht as usize, usersize_delta)n }n 'n }' // I hate this.n self.num_usercount = self.num_usercount.wrapping_add(usersize_delta as usize);n' ''n '// '''''''''update_offsets'''''''''d'a'e'h'''''''''e''''''''''''''''''''''''''''''''''isize';''''s'i' 's'a' 'e'z''''e'i's'_'d'l'o' '-' 'e'z'i's'i'''''''i'u' 's'a' 'e'z'i's'_'w'e'n'''z'i's'u' 's'a' ''''''''heigh''ts'.'e'd'''o'n'.'f'l'e's'(height: usize, by: isize)'.'r'o's'r'u'c' ';' '=' 'e'z'i's'_'w'e'n' 't'e'l' 'o'm''''''''''''''''''''''n ';')'t'e's'f'f'o' ','m'e't'i'('F' ''''get_usersize''''m''''n ';''e't'i'(_item: &Self::Item)':':'C' '=' 'e'z'i's'_'d'l'o' 't'e'l' ';')''''''e'r'r'u'c'.'r'o's'r'u'c' '=' 'm'e't'i' 't'e'l' 'lf.head.height as usize, usersize_delta)n }n // I hate this.n self.num_usercount = self.num_usercount.wrapping_add(usersize_delta as usize'''n '''''''''''''''''''>'F'<'''''''''''''''''''''','e'z'i's'u' ''n '''''''''''''''''''''''' ':''''''''e'z'i's'u'''''''n'i' ','m'e'' 'let (mut cursor, offset) = self.i''' 'ter_at_userpos(userpos);n' 't'i''' ')'''''''''''''m'e't'I':':'C' 't'u'm'&'('e'c'n'O'n'F' ':'F' 'e'r'e'h'w' '''''''' }''n 'n ' '{' ')'':'s'o'p'''''''i's'r'e's'u' ''''''''''''''''''''F' ':'n'f'_'y'f'i'd'o'm' ','f'l'e's' 't'u'm'&'('t'a'_'y'f'i'd'o''''o'm' 'n'f' 'b'u'p' 'n ' ');nn replaced_items -= replaced_items_here;n // We'll hop to the next Node at the start of the next loopn // iteration if needed.n cursor.local_index += replaced_items_here;nn for i in 0..self.head.height as usize {n cursor.entries[i].skip_usersize += new_usersize;n }n cursor.userpos += new_usersize;nn notify(dest, ItemMarker {n ptr: e,n _phantom: PhantomData,n });n }nn // Ok now one of two things must be true. Either we've 'n ''''''dbg_check_cursor_at'''''''r''''''''''''''s'''''''''''''''''''s';''''m'e't'i'_'d'e't'r'e's'n'i'_'m'u'n'o'p'r'e's'u'_'t'r'a't's'o's'r'u'''''''''''''o's'r'y'c'&'(cursor: &Cursor<C>, userpos: usize, plus_items: usize)'''''_'g'b'd'.'f'l'e's'''''_'g'b'd' 'run out o'// 'fn // items to remove, or we''// 've run out of items to insert.n 'n ''''''replace_item''''''''''''''''''t' ''&mut Self::no_noti'''' // TODO: Consider concatenating end into contents then just calln // insert_at_iter once.''n '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'e'c'n'o' 'r'e't'i'_'t'a'_'t'r'e's'n'i' 'l'l'a'c' 't's'u'j' 'n'e'h't' '''' ''''.'s't'n'e't'n'o'c' 'o't'n'i'''''''n'o' 'd'n'e' 'g'n'i't'a'n'e't'a'c'n'o'c'''''''g'n'i's'u'f' 'r'e'd'i's'n'o'C' ':'O'D'O'T' '/'/' 'n ' ';'''fy''r'a't's''''' ','r'o's'r'u'c' 't'u'm'&'(cursor: &mut Cursor<C>, new_item: C::Item, notify: Notify)''''''a'l'p'e'r'.'f'l'e's' ' if inserted_cont'// 'ent.len() > '// '0 {n // Insert!n debug_assert!(removed_items == 0'// ');n self.insert_at_iter(cursor, inserted_content, &mut notify);'// 'n } else if removed_items > 0 {n self.del_at_iter(cursor, removed_items);n }n }nn fn dbg_check_cursor_at(&self, cursor: &Cursor<C>, userpos: usize, plus_items: usize) {n if cfg!(debug_assertions) {n let (mut c2, _) = self.iter_at_userpos(userpos);n c2.advance_by_items(plus_items, self.head.height);n assert_eq!(cursor, &c2);n }n }nn fn no_notify(_items: &[C::Item], _marker: ItemMarker<C>) {}nn pub fn replace_at<I>(&mut self, mut start_userpos: usize, removed_items: usize, mut inserted_content: I) where I: ExactSizeIterator<Item=C::Item> {n start_userpos = min(start_userpos, self.get_userlen());nn let (mut cursor, offset) = self.iter_at_userpos(start_userpos);n assert_eq!(offset, 0, 'Splitting nodes not yet supported');nn let num_inserted_items = inserted_content.len();n unsafe { self.replace_at_iter(&mut cursor, removed_items, &mut inserted_content, Self::no_notify); }nn if cfg!(debug_assertions) {n let (mut c2, _) = self.iter_at_userpos(start_userpos);n c2.advance_by_items(num_inserted_items, self.head.height);n if &cursor != &c2 { panic!('Invalid cursor after replace'); }n }n }nn pub fn replace_at_slice(&mut self, start_userpos: usize, removed_items: usize, inserted_content: &[C::Item]) where C::Item: Copy {n self.replace_at(start_userpos, removed_items, inserted_content.iter().copied());n }nn pub fn insert_at<I>(&mut self, mut userpos: usize, mut contents: I) where I: ExactSizeIterator<Item=C::Item> {n if contents.len() == 0 { return; }n let num_inserted_items = contents.len();n n userpos = min(userpos, self.get_userlen());n let (mut cursor, offset) = self.iter_at_userpos(userpos);nn unsafe {n if offset == 0 {n self.insert_at_iter(&mut cursor, &mut contents, &mut Self::no_notify);nn self.dbg_check_cursor_at(&cursor, userpos, num_inserted_items);n } else {n let current_item = cursor.current_item();n let (start, end) = C::split_item(current_item, offset);n // Move the cursor back to the start of the item we'ren // splitting.n cursor.move_to_item_start(self.head.height, offset);n // This feels pretty inefficient; but its probably fine.n self.replace_at_iter(&mut cursor, 1, &mut iter::once(start), &mut Self::no_notify);n self.insert_at_iter(&mut cursor,''' ''n ' // TODO: Don't export this.' '' '''''''''''''''''''''''''':':'t'm'f':':'d't's''''''g'u'b'e'D' ':'m'e't'I':':'C' 'e'r'e'h'w' ' 'n pub fn print(&s' 'elf) {' 'n println!('items: {}tuserlen: {}, height: {}', self.num_items, self.get_userlen(), sel''f.hea' 'd.height);n' 'n' ' ' ' print!('HEAD:');n' ' '' for s in self.head.nexts() {n' ' ' ' ' ' print!(' |{} ', s.skip''_user' 'size);n' ' }n' ' ' ' println!('');n' 'n' ' ' ' use std::collections::HashMap;n' ' let m' 'ut ptr_to_id = HashMap::new();n' ' //' ' ptr_to_id.insert(std::ptr::null()' ', usize::MAX);n' ' for (i, node) in s' 'elf.iter().enumerate() {n' ' ' ' print!('{}:', i);n' ' ' ' ptr_to_id' '.insert(node as *const _, i);n' ' fo' 'r s in node.nexts() {n' ' print!(' |{} ', s.' 'skip_usersize);n' ' }n'' ' ' ' ' print!(' : {:?}', node.content_slice());n' '' ' ' ' if let S' 'ome(id) = ptr_' 'to_id.get(&(node.parent as *const _)) {n' ' print!(' (parent: {})', id);n' ' }n' ' print!(' (pointer: {:?})', node as *const _);n' 'n' ' println!();n' ' }n' ' }' 'n ' ' &mut contents, &mut Self::no_notify);nn // There's no clean way to keep the cursor steady for the finaln // insert. We'll just make sure the cursor is in the rightn // position before that call for now.n self.dbg_check_cursor_at(&cursor, userpos, num_inserted_items);nn self.insert_at_iter(&mut cursor, &mut iter::once(end), &mut Self::no_notify);n }n }nn }nn pub fn insert_at_slice(&mut self, userpos: usize, contents: &[C::Item]) where C::Item: Copy {n self.insert_at(userpos, contents.iter().copied())n'' dealloc(p as *mut u8, Self::layout_with_height((*p).height));n }nn fn content_slice(&self) -> &[C::Item] {n let slice = &self.items[..self.num_items as usize];n unsafe { maybeinit_slice_get_ref(slice) }n }nn //'' ''T'// ''''// 'he height is at least 1, so this is always valid.n fn first_skip_'// 'entry''<''// 'a>(&self) -> &'a SkipEntry<C> '// '{n ''unsa'// 'fe { &*self.nex'// 'ts.as_'// 'ptr() }n '' }nn'//'' ' '// 'fn'// ' f''impl<C: ListConfig> From<Vec<C::Item>> for Ski'// 'pList<C> {n fn from(s: Vec<C::Item>) -> Ski'// 'pList<C> {n SkipList::new_from_iter(s.in'// 'to_ite'// 'r())n }n'n'}n''i''rst_skip_e''''''''Ex'I'actSizeIterato''''''''''''ExactSizeIter'''// ''f''n'''''''I' ':'r'e't'i' from(s: Vec<C::Item>) -> SkipList<C>''''r'''e't'i' {''n// SkipList::new_from_iter(s.into_iter())''n// }'ato''''''='m'e't'I'''''''''' '>'m'e't'I':':'C'<'r''''a'x'E' ':'I' 'e'r'e'h'w'''''''w' ''''''''>'m'e't'I':':'C'<'r''''a'x'E' ':'I'''' let mut rope = Self::new();' '''n rope.insert_at_sl' 'ice(0, s);''n ropen' ','ntry_mut<'a>(&mut self) -> &'a mut SkipEntry<C> {n unsafe { &mut *self.nexts.as_mut_ptr() }n }nn // TODO: Rename to len() ?n fn get_userlen(&self) -''''r'''into_iter()'''''o't'n'i'.'s''''e't'i'''>'' ''u''s''ize {n self.first_skip_entry().skip_usersizen }n n fn get_next_ptr(&self) -> *mut Node<C> {n self.first_skip_entry().noden }n}nnstruct NodeIter<'a, C: ListConfig>(Option<&'a Node<C>>);nimpl<'a, C: ListConfig> Iterator for NodeIter<'a, C''> {n type Item = &'a Node<C>;nn fn next(&mut self) -> Option<&'a Node<C>> {n let prev = self.0;n if let Some(n) = self.0 {n *self = NodeIter(unsafe { n.first_skip_entry().node.as_ref() });n }n prevn }n}nn/// This is a set of pointers with metadata into a location in the list neededn/// to skip ahead, delete and insert in items. A cursor is reasonably heavyn/// weight - we fill in and maintain as many entries as the height of the listn/// dictates.n///n/// This is not needed for simply iterating sequentially through nodes and data.n/// For that look at NodeIter.n///n/// Note most/all methods using cursors are unsafe. This is because cursors usen/// raw mutable pointers into the list, so when used the following rules have ton/// be followed:n///n/// - Whenever a write happens (insert/remove/replace), any cursor not passed ton/// the write function is invalid.n/// - While a cursor is held the SkipList struct should be considered pinned andn/// must not be moved or deletedn#[derive(Copy, Clone)]npub struct Cursor<C: ListConfig> {n // TODO: Add a phantom lifetime reference to the skip list root for safety.nnn /// The global user position of the cursor in the entire list. This is usedn /// for when the max seen height increases, so we can populate previouslyn /// unused entries in the cursor and in the head node.n ///n /// This field isn't strictly necessary - earlier versions tacked this on ton /// the last item in entries... I'm still not sure the cleanest way to don /// this.n userpos: usize,nn /// When the userpos of an entry is 0 (totally valid and useful), a cursorn /// becomes ambiguous with regard to where exactly its pointing in then /// current entry. This is used to resolve that ambiguity.n local_index: usize,nn entries: [SkipEntry<C>; MAX_HEIGHT],n}nnimpl<C: ListConfig> Cursor<C> {n fn update_offsets(&mut self, height: usize, by: isize) {n for i in 0..height {n unsafe {n // This is weird but makes sense when you realise the nexts inn // the cursor are pointers into the elements that have then // actual pointers.n // Also adding a usize + isize is awful in rust :/n let skip = &mut (*self.entries[i].node).nexts_mut()[i].skip_usersize;n *skip = skip.wrapping_add(by as usize);n }n }n }nn /// Move a cursor to the start of the next node. Returns the new node (or an /// nullptr if this is the end of the list).n fn advance_node(&mut self) -> *mut Node<C> {n unsafe {n let SkipEntry { node: e, skip_usersize: offset } = self.entries[0];n // offset tells us how far into the current element we are (inn // usersize). We need to increment the offsets by the entry'sn // remaining length to get to the start of the next node.n let advance_by = (*e).get_userlen() - offset;n let next = (*e).get_next_ptr();n let height = (*next).height as usize;nn for i in 0..height {n self.entries[i] = SkipEntry {n node: next,n skip_usersize: 0n };n }nn for i in height..self.entries.len() {n self.entries[i].skip_usersize += advance_by;n }nn self.userpos += advance_by;n self.local_index = 0;nn nextn }n }nn fn is_at_node_end(&self) -> bool {n self.local_index == unsafe { (*self.here_ptr()).num_items } as usizen }nn fn advance_item(&mut self, height: u8) {n if self.is_at_node_end() { self.advance_node(); }n let usersize = C::get_usersize(unsafe { self.current_item() });nn for entry in &mut self.entries[0..height as usize] {n entry.skip_usersize += usersize;n }n self.userpos += usersize;n self.local_index += 1;n }nn fn advance_by_items(&mut self, num: usize, height: u8) {n for _ in 0..num { self.advance_item(height); }n }nn fn move_to_item_start(&mut self, height: u8, offset: usize) {n for entry in &mut self.entries[0..height as usize] {n entry.skip_usersize -= offset;n }n self.userpos -= offset;n }nn unsafe fn current_item(&mut self) -> &C::Item {n let node = &*self.here_ptr();n debug_assert!(node.num_items as usize >= self.local_index);n &*(node.items[self.local_index].as_ptr())n }nn /// Get the pointer to the cursor's current noden fn here_ptr(&self) -> *mut Node<C> {n self.entries[0].noden }n}nnimpl<C: ListConfig> PartialEq for Cursor<C> {n /// Warning: This returns false if one cursor is at the end of a node, andn /// the other at the start of the next node. Almost all code in this libraryn /// leaves cursors at the end of nodes, so this shouldn't matter too much inn /// practice.n fn eq(&self, other: &Self) -> bool {n if self.userpos != other.userposn || self.local_index != other.local_index {return false; }nn for i in 0..MAX_HEIGHT {n let a = &self.entries[i];n let b = &other.entries[i];n if a.node != b.node || a.skip_usersize != b.skip_usersize { return false; }n }n truen }n}nimpl<C: ListConfig> Eq for Cursor<C> {}nnimpl<C: ListConfig> fmt::Debug for Cursor<C> {n fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n f.debug_struct('Cursor')n .field('userpos', &self.userpos)n .field('local_index', &self.local_index)n .finish()n }n}nn// None of the rust builtins give me what I want, which is a copy-free iteratorn// to owned items in a MaybeUninit array. Eh; its easy enough to make my own.nstruct UninitOwnedIter<'a, C: ListConfig> {n // Based on the core slice IterMut implementation.n ptr: NonNull<C::Item>,n end: *mut C::Item,n _marker: PhantomData<&'a SkipList<C>>n}nnimpl<'a, C: ListConfig> UninitOwnedIter<'a, C> {n /// Make a slice we can iterate from and steal data from without droppingn /// content. This is unsafe:n ///n /// - If the iterator isn't fully drained then remaining items will ben /// forgotten (they are not dropped).n /// - The slice passed in here must be initialized or undefined behaviourn /// will hit us.n ///n /// After iterating, the contents are uninit memory.n unsafe fn from_slice(slice: &[MaybeUninit<C::Item>]) -> Self {n let ptr = slice.as_ptr() as *mut C::Item; // Safe.n let end = ptr.add(slice.len());nn UninitOwnedIter {n ptr: NonNull::new_unchecked(ptr),n end,n _marker: PhantomDatan }n }n}nnimpl<'a, C: ListConfig> Iterator for UninitOwnedIter<'a, C> {n type Item = C::Item;nn fn next(&mut self) -> Option<Self::Item> {n if self.ptr.as_ptr() == self.end {n Nonen } else {n let ptr = self.ptr;n self.ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().offset(1)) };n Some(unsafe { ptr.as_ptr().read() })n }n }nn fn size_hint(&self) -> (usize, Option<usize>) {n let size = (self.end as usize - self.ptr.as_ptr() as usize) / mem::size_of::<C::Item>();n (size, Some(size))n }n}nn// TODO: Stolen from MaybeUninit::uninit_array. Replace with the real uninit_array when stable.n#[inline(always)]nfn uninit_items_array<T>() -> [MaybeUninit<T>; NODE_NUM_ITEMS] {n unsafe { MaybeUninit::<[MaybeUninit<T>; NODE_NUM_ITEMS]>::uninit().assume_init() }n}nn// TODO: Stolen from MaybeUninit::slice_get_ref. Replace when available.n#[inline(always)]nunsafe fn maybeinit_slice_get_ref<T>(slice: &[MaybeUninit<T>]) -> &[T] {n // SAFETY: casting slice to a `*const [T]` is safe since the caller guarantees thatn // `slice` is initialized, and`MaybeUninit` is guaranteed to have the same layout as `T`.n // The pointer obtained is valid since it refers to memory owned by `slice` which is an // reference and thus guaranteed to be valid for reads.n &*(slice as *const [MaybeUninit<T>] as *const [T])n}nnnimpl<C: ListConfig> SkipList<C> {n pub fn new() -> Self {n SkipList::<C> {n num_items: 0,n num_usercount: 0,n rng: None,n head: Node {n items: uninit_items_array(),n num_items: 0,n height: 1, // Stores max height of list nodesn parent: ptr::null_mut(),n nexts: [],n },n _nexts_padding: [SkipEntry::new_null(); MAX_HEIGHT],n }n }nn pub fn init_rng_from_seed(&mut self, seed: u64) {n self.rng = Some(SmallRng::seed_from_u64(seed));n }nn fn get_rng(&mut self) -> &mut SmallRng {n // I'm sure there's a nicer way to implement this.n if self.rng.is_none() {n // We'll use a stable RNG in debug mode so the tests are stable.n if cfg!(debug_assertions) {n self.init_rng_from_seed(123);n } else {n self.rng = Some(SmallRng::from_entropy());n }n }n self.rng.as_mut().unwrap()n }nn pub fn new_from_slice(s: &[C::Item]) -> Self where C::Item: Copy {n let mut rope = Self::new();n rope.insert_at(0, s);n ropen }nn pub fn get_userlen(&self) -> usize {n self.num_usercountn }nn fn iter(&self) -> NodeIter<C> { NodeIter(Some(&self.head)) }n n pub fn len_items(&self) -> usize {n self.num_items as usizen }nn fn heads_mut(&mut self) -> &mut [SkipEntry<C>] {n unsafe {n std::slice::from_raw_parts_mut(self.head.nexts.as_mut_ptr(), self._nexts_padding.len())n }n }nn fn is_head(&self, node: *const Node<C>) -> bool {n node as *const _ == &self.head as *const _n }nn /// Walk the list and validate internal constraints. This is used forn /// testing the structure itself, and should generally not be called byn /// users.n pub fn check(&self) {n // #[cfg(test)]n {n // self.print();n assert!(self.head.height >= 1);n assert!(self.head.height <= MAX_HEIGHT_U8);nn let head_ptr = &self.head as *const _ as *mut _;n // let skip_over = self.get_top_entry();n // println!('Skip over skip chars {}, num bytes {}', skip_over.skip_items, self.num_bytes);nn let mut prev: [*const Node<C>; MAX_HEIGHT] = [ptr::null(); MAX_HEIGHT];nn let mut iter = [SkipEntry {n // Bleh.n node: head_ptr,n // The skips will store the total distance travelled since then // start of this traversal at each height. All the entries aboven // head.height are ignored though.n skip_usersize: 0n }; MAX_HEIGHT];nn let mut num_items = 0;n let mut num_usercount = 0;nn for (_i, n) in self.iter().enumerate() {n // println!('visiting {:?}', n.as_str());n if !self.is_head(n) { assert!(n.num_items > 0); }n assert!(n.height <= MAX_HEIGHT_U8);n assert!(n.num_items as usize <= NODE_NUM_ITEMS);nn // Make sure the number of items matches the countn let local_count = C::userlen_of_slice(n.content_slice());n assert_eq!(local_count, n.get_userlen());nn let expect_parent = if self.is_head(n) {n ptr::null() // The head's parent is nulln } else if n.height == self.head.height {n &self.head as *const _ // Max height nodes point back to headn } else {n prev[n.height as usize]n };nn // println!('visiting {} {:?}', i, n as *const _);n // dbg!(n as *const _);n // dbg!((n as *const _, (*n).height));n // dbg!(n.parent);n // dbg!(&self.head as *const _);nn assert_eq!(n.parent as *const _, expect_parent, 'invalid parent');n n for (i, entry) in iter[0..n.height as usize].iter_mut().enumerate() {n assert_eq!(entry.node as *const _, n as *const _);n assert_eq!(entry.skip_usersize, num_usercount);nn // println!('replacing entry {:?} with {:?}', entry, n.nexts()[i].node);n prev[i] = n;n entry.node = n.nexts()[i].node;n entry.skip_usersize += n.nexts()[i].skip_usersize;n }nn num_items += n.num_items as usize;n num_usercount += n.get_userlen();nn // Check the value returned by the iterator functions matches.n let (mut normal_iter, local_offset) = self.iter_at_userpos(num_usercount);n assert_eq!(local_offset, 0);nn // Dirty hack. If n has 0-sized elements at the end, the normaln // cursor won't be at the end...n while normal_iter.here_ptr() != n as *const _ as *mut _ {n normal_iter.advance_node();n }n normal_iter.local_index = n.num_items as usize;n let node_iter = unsafe { self.iter_at_node(n, n.get_userlen(), n.num_items as usize) };n assert_eq!(normal_iter, node_iter);n }nn for entry in iter[0..self.head.height as usize].iter() {n // println!('{:?}', entry);n assert!(entry.node.is_null());n assert_eq!(entry.skip_usersize, num_usercount);n }n n // println!('self bytes: {}, count bytes {}', self.num_bytes, num_bytes);n assert_eq!(self.num_items, num_items);n assert_eq!(self.get_userlen(), num_usercount);n }n }n n n /// Internal function for creating a cursor at a particular location in then /// skiplist. The returned cursor contains list of nodes which point pastn /// the specified position, as well as offsets of how far into theirn /// character lists the specified characters are.n ///n /// Sometimes a call to iter_at_userpos is ambiguous:n ///n /// - The item can contain items with zero usersize. The cursor could pointn /// to any of them.n /// - If the location is at the end of a node, it is equally valid to returnn /// a position at the start of the next node.n ///n /// Because its impossible to move backwards in the list, iter_at_userposn /// returns the first admissible location with the specified userpos.n /// n /// Returns (cursor, offset into the specified item).n ///n /// TODO: This should be Pin<&self>.n fn iter_at_userpos(&self, target_userpos: usize) -> (Cursor<C>, usize) {n assert!(target_userpos <= self.get_userlen());nn let mut e: *const Node<C> = &self.head;n let mut height = self.head.height as usize - 1;n n let mut offset = target_userpos; // How many more items to skipnn // We're populating the head node pointer to simplify the case when then // iterator grows. We could put offset into the skip_usersize but itn // would only be *mostly* correct, not always correct. (Since cursorn // entries above height are not updated by insert.)n let mut cursor = Cursor {n entries: [SkipEntry {n node: &self.head as *const _ as *mut _,n skip_usersize: usize::MAXn }; MAX_HEIGHT],n local_index: 0,n userpos: target_userpos,n };nn loop { // while height >= 0n let en = unsafe { &*e };n let next = en.nexts()[height];n let skip = next.skip_usersize;n if offset > skip {n // Go right.n debug_assert!(e == &self.head || en.num_items > 0);n offset -= skip;n e = next.node;n assert!(!e.is_null(), 'Internal constraint violation: Reached rope end prematurely');n } else {n // Record this and go down.n cursor.entries[height] = SkipEntry {n skip_usersize: offset,n node: e as *mut Node<C>, // This is pretty grossn };nn if height == 0 { break; } else { height -= 1; }n }n };nn // We should always land within the node we're pointing to.n debug_assert!(offset <= unsafe { &*cursor.here_ptr() }.get_userlen());nn // We've found the node. Now look for the index within the node.n let en = unsafe { &*e };n let mut index = 0;nn while offset > 0 {n assert!(index < en.num_items as usize);n n let usersize = C::get_usersize(unsafe { &*en.items[index].as_ptr() });n if usersize > offset { break; } // We're in the middle of an item.n offset -= usersize;n index += 1;n }n cursor.local_index = index;nn (cursor, offset)n }nn unsafe fn iter_at_node(&self, n: *const Node<C>, mut offset: usize, local_index: usize) -> Cursor<C> {n let mut n = n as *mut Node<C>; // We don't mutate, but we need a mut ptr.nn let mut cursor = Cursor {n userpos: 0, // We'll set this later.n local_index: local_index,n entries: [SkipEntry {n node: &self.head as *const _ as *mut _,n skip_usersize: usize::MAXn }; MAX_HEIGHT],n };nn let mut h = 0;n loop {n while h < (*n).height as usize {n cursor.entries[h] = SkipEntry {n node: n,n skip_usersize: offsetn };nn h += 1;n }nn let parent = (*n).parent;n // Reached the head.n if parent.is_null() { break; }nn // If we're the same height as the parent its fine.n debug_assert!((*parent).height as usize > hn || (self.is_head(parent) && (*parent).height as usize == h));nn // Walk from parent back to n, figuring out the offset.n let mut c = parent;n // let walk_height = (*parent).height as usize - 2;n let walk_height = (*n).height as usize - 1;n while c != n {n let elem = (*c).nexts()[walk_height];n offset += elem.skip_usersize;n c = elem.node;n }nn n = parent;n }nn cursor.userpos = offset;n cursorn }nn pub fn iter_at_marker(&mut self, marker: ItemMarker<C>, query: &<C::Item as Queryable>::Query) -> Cursor<C> where C::Item: Queryable {n // The marker gives us a pointer into a node. Find the item.n unsafe {n let n = marker.ptr;nn let mut offset: usize = 0;n let mut local_index = None;n for (i, item) in (*n).content_slice().iter().enumerate() {n if let Some(item_offset) = item.contains_item(query) {n offset += item_offset;n local_index = Some(i);n break;n } else {n offset += C::get_usersize(item);n }n }nn let local_index = local_index.expect('Invalid marker - item not found in node');n self.iter_at_node(n, offset, local_index)n }n }nn // Internal fn to create a new node at the specified iterator filled withn // the specified content. The passed cursor should point at the end of then // previous node. It will be updated to point to the end of the newlyn // inserted content.n // unsafe fn insert_node_at(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item], new_userlen: usize, move_cursor: bool) {n unsafe fn insert_node_at<Notify, I>(&mut self, cursor: &mut Cursor<C>, contents: &mut I, num_items: usize, move_cursor: bool, notify: &mut Notify)n where Notify: FnMut(&[C::Item], ItemMarker<C>), I: Iterator<Item=C::Item> {nn // println!('Insert_node_at {} len {}', contents.len(), self.num_bytes);n // debug_assert_eq!(new_userlen, C::userlen_of_slice(contents));n assert!(num_items <= NODE_NUM_ITEMS);n debug_assert!(contents.size_hint().0 >= num_items);nn let new_node_ptr = Node::alloc(self.get_rng());n let new_node = &mut *new_node_ptr;n new_node.num_items = num_items as u8;nn for (slot, item) in new_node.items[..num_items].iter_mut().zip(contents) {n (slot.as_mut_ptr() as *mut C::Item).write(item); // Write makes sure we don't drop the old value.n }nn let new_userlen = C::userlen_of_slice(new_node.content_slice());nn let new_height = new_node.height;n let new_height_usize = new_height as usize;nn let mut head_height = self.head.height as usize;n while head_height < new_height_usize {n // This seems weird given we're about to overwrite these valuesn // below. What we're doing is retroactively setting up the cursorn // and head pointers *as if* the height had been this high alln // along. This way we only have to populate the higher head valuesn // lazily.n let total_userlen = self.num_usercount;n let nexts = self.heads_mut();n nexts[head_height].skip_usersize = total_userlen;n cursor.entries[head_height].skip_usersize = cursor.userpos;nn head_height += 1; // This is ugly.n self.head.height += 1;n }nn new_node.parent = if new_height_usize == MAX_HEIGHT {n &self.head as *const _ as *mut _n } else { cursor.entries[new_height_usize].node };nn for i in 0..new_height_usize {n let prev_skip = &mut (*cursor.entries[i].node).nexts_mut()[i];n let new_nexts = new_node.nexts_mut();nn // The new node points to the successor (or null)n new_nexts[i] = SkipEntry {n node: prev_skip.node,n skip_usersize: new_userlen + prev_skip.skip_usersize - cursor.entries[i].skip_usersizen };nn // The previous node points to the new noden *prev_skip = SkipEntry {n node: new_node_ptr,n skip_usersize: cursor.entries[i].skip_usersizen };nn // Move the iterator to the end of the newly inserted node.n if move_cursor {n cursor.entries[i] = SkipEntry {n node: new_node_ptr,n skip_usersize: new_userlenn };n }n }nn for i in new_height_usize..head_height {n (*cursor.entries[i].node).nexts_mut()[i].skip_usersize += new_userlen;n if move_cursor {n cursor.entries[i].skip_usersize += new_userlen;n }n }nn // Update parents.n if new_height_usize > 1 {nn let mut n = new_node_ptr;n let mut skip_height = 0;nn loop {n n = (*n).nexts_mut()[skip_height].node;n if n.is_null() || (*n).height >= new_height { break; }n n (*n).parent = new_node_ptr;n skip_height = usize::max(skip_height, (*n).height as usize - 1);n }n }n n self.num_items += num_items;n self.num_usercount += new_userlen;n if move_cursor {n cursor.userpos += new_userlen;n cursor.local_index = num_items;n }nn notify(new_node.content_slice(), ItemMarker {n ptr: new_node_ptr,n _phantom: PhantomDatan });n }nn // unsafe fn insert_at_iter(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item]) {n unsafe fn insert_at_iter<Notify, I>(&mut self, cursor: &mut Cursor<C>, contents: &mut I, notify: &mut Notify)n where Notify: FnMut(&[C::Item], ItemMarker<C>), I: ExactSizeIterator<Item=C::Item> {n // iter specifies where to insert.nn let mut e = cursor.here_ptr();nn // The insertion offset into the destination node.n assert!(cursor.userpos <= self.num_usercount);n assert!(cursor.local_index <= (*e).num_items as usize);nn // We might be able to insert the new data into the current node, depending onn // how big it is.n let num_inserted_items = contents.len();nn // Can we insert into the current node?n let mut insert_here = (*e).num_items as usize + num_inserted_items <= NODE_NUM_ITEMS;nn // Can we insert into the start of the successor node?n if !insert_here && cursor.local_index == (*e).num_items as usize && num_inserted_items <= NODE_NUM_ITEMS {n // We can insert into the subsequent node if:n // - We can't insert into the current noden // - There _is_ a next node to insert inton // - The insert would be at the start of the next noden // - There's room in the next noden if let Some(next) = (*e).first_skip_entry_mut().node.as_mut() {n if next.num_items as usize + num_inserted_items <= NODE_NUM_ITEMS {n cursor.advance_node();n e = next;nn insert_here = true;n }n }n }nn let item_idx = cursor.local_index;n let e_num_items = (*e).num_items as usize; // convenience.nn if insert_here {n // println!('insert_here {}', contents);n // First push the current items later in the arrayn let c = &mut (*e).items;n if item_idx < e_num_items {n // Can't use copy_within because Item doesn't necessarilyn // implement Copy. Memmove the existing items.n ptr::copy(n &c[item_idx],n &mut c[item_idx + num_inserted_items],n (*e).num_items as usize - item_idx);n }nn // Then copy in the new items. Can't memcpy from an iterator, butn // the optimizer should make this fast.n let dest_content_slice = &mut c[item_idx..item_idx + num_inserted_items];n for (slot, item) in dest_content_slice.iter_mut().zip(contents) {n // Do not drop the old items - they were only moved.n slot.as_mut_ptr().write(item);n }n let dest_content_slice = maybeinit_slice_get_ref(dest_content_slice);nn (*e).num_items += num_inserted_items as u8;n self.num_items += num_inserted_items;n let num_inserted_usercount = C::userlen_of_slice(dest_content_slice);n self.num_usercount += num_inserted_usercount;nn // .... aaaand update all the offset amounts.n cursor.update_offsets(self.head.height as usize, num_inserted_usercount as isize);nn // Usually the cursor will be discarded after one change, but forn // consistency of compound edits we'll update the cursor to point ton // the end of the new content.n for entry in cursor.entries[0..self.head.height as usize].iter_mut() {n entry.skip_usersize += num_inserted_usercount;n }n cursor.userpos += num_inserted_usercount;n cursor.local_index += num_inserted_items;nn notify(dest_content_slice, ItemMarker {n ptr: e,n _phantom: PhantomDatan });n } else {n // There isn't room. We'll need to add at least one new node to then // list. We could be a bit more careful here and copy as much asn // possible into the current node - that would decrease the numbern // of new nodes in some cases, but I don't think the performancen // difference will be large enough to justify the complexity.nn // If we're not at the end of the current node, we'll need to removen // the end of the current node's data and reinsert it later.n let num_end_items = e_num_items - item_idx;nn let (end_items, end_usercount) = if num_end_items > 0 {n // We'll mark the items as deleted from the node, while leavingn // the data itself there for now to avoid a copy.nn // Note that if we wanted to, it would also be correct (andn // slightly more space efficient) to pack some of the newn // string's characters into this node after trimming it.n let end_items = &(*e).items[item_idx..e_num_items];n (*e).num_items = item_idx as u8;n let end_usercount = (*e).get_userlen() - cursor.entries[0].skip_usersize;nn cursor.update_offsets(self.head.height as usize, -(end_usercount as isize));nn // We need to trim the size off because we'll add the charactersn // back with insert_node_at.n self.num_usercount -= end_usercount;n self.num_items -= num_end_items;nn (Some(end_items), end_usercount)n } else {n (None, 0)n };nn // Now we insert new nodes containing the new character data. Then // data is broken into pieces with a maximum size of NODE_NUM_ITEMS.n // As further optimization, we could try and fit the last piece inton // the start of the subsequent node.n let mut items_remaining = num_inserted_items;n while items_remaining > 0 {n let insert_here = usize::min(items_remaining, NODE_NUM_ITEMS);n self.insert_node_at(cursor, contents, insert_here, true, notify);n items_remaining -= insert_here;n }nn // TODO: Consider recursively calling insert_at_iter() here insteadn // of making a whole new node for the remaining content.n if let Some(end_items) = end_items {n // Passing false to indicate we don't want the cursor updatedn // after this - it should remain at the end of the newlyn // inserted content, which is *before* this end bit.n self.insert_node_at(cursor, &mut UninitOwnedIter::<C>::from_slice(end_items), end_items.len(), false, notify);n }n }n }nn // unsafe fn insert_at_iter(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item]) {n // self.insert_at_iter_and_notify(cursor, contents, Self::no_notify);n // }nn /// Interestingly unlike the original, here we only care about specifyingn /// the number of removed items by counting them. We do not use usersize inn /// the deleted item count.n ///n /// If the deleted content occurs at the start of a node, the cursor passedn /// here must point to the end of the previous node, not the start of then /// current node.n unsafe fn del_at_iter(&mut self, cursor: &mut Cursor<C>, mut num_deleted_items: usize) {n if num_deleted_items == 0 { return; }nn let mut item_idx = cursor.local_index;n let mut e = cursor.here_ptr();n while num_deleted_items > 0 {n // self.print();n // if cfg!(debug_assertions) { self.check(); }n if item_idx == (*e).num_items as usize {n let entry = (*e).first_skip_entry();n // End of current node. Skip to the start of the next one. We'ren // intentionally not updating the iterator because if we deleten // a whole node we need the iterator to point to the previousn // element. And if we only delete here, the iterator doesn'tn // need to be moved.n e = entry.node;n if e.is_null() { panic!('Cannot delete past the end of the list'); }n item_idx = 0;n }nn let e_num_items = (*e).num_items as usize;n let removed_here = min(num_deleted_items, e_num_items - item_idx);n n let height = (*e).height as usize;n let removed_userlen;nn if removed_here < e_num_items || e as *const _ == &self.head as *const _ {n // Just trim the node down.n let trailing_items = e_num_items - item_idx - removed_here;n n let c = &mut (*e).items;n removed_userlen = C::userlen_of_slice(maybeinit_slice_get_ref(&c[item_idx..item_idx + removed_here]));n if trailing_items > 0 {n ptr::copy(n &c[item_idx + removed_here],n &mut c[item_idx],n trailing_items);n }nn (*e).num_items -= removed_here as u8;n self.num_items -= removed_here;n self.num_usercount -= removed_userlen;nn for s in (*e).nexts_mut() {n s.skip_usersize -= removed_userlen;n }n } else {n // Remove the node from the skip list entirely. e should be then // next node after the position of the iterator.n assert_ne!(cursor.here_ptr(), e);nn removed_userlen = (*e).get_userlen();n let next = (*e).first_skip_entry().node;nn // println!('removing {:?} contents {:?} height {}', e, (*e).content_slice(), height);nn for i in 0..height {n let s = &mut (*cursor.entries[i].node).nexts_mut()[i];n s.node = (*e).nexts_mut()[i].node;n s.skip_usersize += (*e).nexts()[i].skip_usersize - removed_userlen;n }nn self.num_items -= (*e).num_items as usize;n self.num_usercount -= removed_userlen;nn // Update parents.n if height > 1 {n let mut n = e;n // let new_parent = cursor.entries[height - 1].node;nn // If you imagine this node as a big building, we need ton // update the parent of all the nodes we cast a shadow over.n // So, if our height is 3 and the next nodes have heights 1n // and 2, they both need new parents.n let mut parent_height = 1;n let cursor_node = cursor.here_ptr();n let cursor_node_height = (*cursor_node).height as usize;n let mut new_parent = if height >= cursor_node_height {n cursor.entries[parent_height].noden } else {n cursor_noden };nn loop {n n = (*n).nexts_mut()[parent_height - 1].node;n if n.is_null() || (*n).height >= height as u8 { break; }n let n_height = (*n).height as usize;n n assert_eq!((*n).parent, e);n assert!(n_height >= parent_height - 1);nn if n_height > parent_height {n parent_height = n_height;n if n_height >= cursor_node_height {n new_parent = cursor.entries[parent_height].noden }n }n n (*n).parent = new_parent;n }n }nn Node::free(e);n e = next;n }nn for i in height..self.head.height as usize {n let s = &mut (*cursor.entries[i].node).nexts_mut()[i];n s.skip_usersize -= removed_userlen;n }nn num_deleted_items -= removed_here;nn // if cfg!(debug_assertions) { self.check(); }n }n }nnn unsafe fn replace_at_iter<Notify, I>(&mut self, cursor: &mut Cursor<C>, mut removed_items: usize, inserted_content: &mut I, mut notify: Notify)n where Notify: FnMut(&[C::Item], ItemMarker<C>), I: ExactSizeIterator<Item=C::Item> {n if removed_items == 0 && inserted_content.len() == 0 { return; }nn // Replace as many items from removed_items as we can with inserted_content.n let mut replaced_items = min(removed_items, inserted_content.len());n removed_items -= replaced_items;nn while replaced_items > 0 {n debug_assert!(inserted_content.len() >= replaced_items);n let mut e = cursor.here_ptr();n if cursor.local_index == (*e).num_items as usize {n // Move to the next item.n e = cursor.advance_node();n if e.is_null() { panic!('Cannot replace past the end of the list'); }n }nn let index = cursor.local_index;nn let e_num_items = (*e).num_items as usize;n let replaced_items_here = min(replaced_items, e_num_items - index);nn let dest = &mut (*e).items[index..index + replaced_items_here];n let old_usersize = C::userlen_of_slice(maybeinit_slice_get_ref(dest));nn // Replace the items themselves. Everything else is commentary.n // Would prefer to use zip() but it wants ownership of inserted_content :/n for slot in dest.iter_mut() {n *slot.as_mut_ptr() = inserted_content.next().unwrap();n }nn let dest = maybeinit_slice_get_ref(dest);n let new_usersize = C::userlen_of_slice(dest);n let usersize_delta = new_usersize as isize - old_usersize as isize;nn if usersize_delta != 0 {n cursor.update_offsets(self.head.height as usize, usersize_delta)n }n // I hate this.n self.num_usercount = self.num_usercount.wrapping_add(usersize_delta as usize);nn replaced_items -= replaced_items_here;n // We'll hop to the next Node at the start of the next loopn // iteration if needed.n cursor.local_index += replaced_items_here;nn for i in 0..self.head.height as usize {n cursor.entries[i].skip_usersize += new_usersize;n }n cursor.userpos += new_usersize;nn notify(dest, ItemMarker {n ptr: e,n _phantom: PhantomData,n });n }nn // Ok now one of two things must be true. Either we've run out ofn // items to remove, or we've run out of items to insert.n if inserted_content.len() > 0 {n // Insert!n debug_assert!(removed_items == 0);n self.insert_at_iter(cursor, inserted_content, &mut notify);n } else if removed_items > 0 {n self.del_at_iter(cursor, removed_items);n }n }nn fn dbg_check_cursor_at(&self, cursor: &Cursor<C>, userpos: usize, plus_items: usize) {n if cfg!(debug_assertions) {n let (mut c2, _) = self.iter_at_userpos(userpos);n c2.advance_by_items(plus_items, self.head.height);n assert_eq!(cursor, &c2);n }n }nn fn no_notify(_items: &[C::Item], _marker: ItemMarker<C>) {}nn pub fn replace_at(&mut self, mut start_userpos: usize, removed_items: usize, inserted_content: &[C::Item]) where C::Item: Copy {n start_userpos = min(start_userpos, self.get_userlen());nn let (mut cursor, offset) = self.iter_at_userpos(start_userpos);n assert_eq!(offset, 0, 'Splitting nodes not yet supported');nn unsafe { self.replace_at_iter(&mut cursor, removed_items, &mut inserted_content.iter().copied(), Self::no_notify); }nn if cfg!(debug_assertions) {n let (mut c2, _) = self.iter_at_userpos(start_userpos);n c2.advance_by_items(inserted_content.len(), self.head.height);n if &cursor != &c2 { panic!('Invalid cursor after replace'); }n }n }nn pub fn insert_at(&mut self, mut userpos: usize, contents: &[C::Item]) where C::Item: Copy {n if contents.len() == 0 { return; }n n userpos = min(userpos, self.get_userlen());n let (mut cursor, offset) = self.iter_at_userpos(userpos);nn unsafe {n if offset == 0 {n self.insert_at_iter(&mut cursor, &mut contents.iter().copied(), &mut Self::no_notify);nn self.dbg_check_cursor_at(&cursor, userpos, contents.len());n } else {n let current_item = cursor.current_item();n let (start, end) = C::split_item(current_item, offset);n // Move the cursor back to the start of the item we'ren // splitting.n cursor.move_to_item_start(self.head.height, offset);n // This feels pretty inefficient; but its probably fine.n self.replace_at_iter(&mut cursor, 1, &mut iter::once(start), &mut Self::no_notify);n self.insert_at_iter(&mut cursor, &mut contents.iter().copied(), &mut Self::no_notify);nn // There's no clean way to keep the cursor steady for the finaln // insert. We'll just make sure the cursor is in the rightn // position before that call for now.n self.dbg_check_cursor_at(&cursor, userpos, contents.len());nn self.insert_at_iter(&mut cursor, &mut iter::once(end), &mut Self::no_notify);n }n }nn'n '''// '''''''drop_in_place'p''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'r'e'n'a'e'l'c' 's'''' 'i' 's'i'h't' 't'u'b' ','e'r'e'h' 'p'o'r'd' 't'n'e'm'e'l'p'm'i''''''''''t'n'm'e'l'e'p'm'i' 't's'u'j' 'd'l'u'o'c' 'e'W''''''''''''' 'e's'u' 'l'l'''e'W' '/'/' ';''(to_drop: *mut T)''''''_'p'o'r'd':':'r't'p' 'll('''MAX_HEIGHT''''X'A'M' ';')'''e'n':':'y'''''p'i'k'S'e {n items: uninit_items_array(),n num_items: 0,n height: height,n parent: ptr::null_mut(),n nexts: [],n };nn for next in (*node).nexts_mut() {n *next = SkipEntry::new_null();n }nn noden }n }nn fn alloc<R: RngCore>(rng: &mut R) -> *mut Node<C> {n Self::alloc_with_height(random_height(rng))n }nn '''''''''''ListConfi'''''''''''''''''''''' '''''''''''''''''''''' '''''n '''''''''nee'''''''''e''' // Could instead call assume_init() on each item but this isn // friendlier to the optimizer.'n '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'r'e'z'i'm'i't'p'o' 'e'h't' 'o't' 'r'e'i'l'd'n'e'i'r'f' 's'i' 's'i'h't''''''''''''''''' 's'i' 's'i'h't' 'k'n'i'h't' 'I' 't'u'b' 'm'e't'i' 'h'c'a'e' 'n'o' ')'('t'i'n'i'_'e'm'u's's'a' 'l'l'a'c' 'd'a'e't's'n'i' 'd'l'u'o'C' '/'/' 'z'i's'u' 's'a''''''''' '{' 'e'f'a's'n'u'' 'ds_dro'':':''''''' ''}' ' '''''{' '' '''>'m'e't'I':':'C'<'p()'''''d'e'e'' ''' '''''drop_in_p''l''ace''''''' 't'u'''as_mut_pt'''''')'('r''''''u'm'_'s'a'.'m'&'''''''(to_d''''''''''_';'' 't'u'm'*' 's'a' 'ro')'p: *mut T)':':'r't'p'' ' 'n''':':'m'e'm'''''''e'n''''e'' 'e'n' 'f'i'' '' }'n '' ''n ''''''''''''''''''num_item''{' '''' '' 's''''m'u''''.']'i'[''' }'n ''n'''''''e'l'.'f'l'e's'.'.'0' 'n'i' 'i''''''''''''' 't'e'l' 'r'o'f' ''n ''''''''''s'm'e't'i'.'f'l'e's''''self.nexts.as_ptr(), self.height as usize' ''' }'n '{' ')'f'l'e's' 't'u'm'&'('p'o'r'd''''D' 'n'f' '''}''n 'n ' '{' '>'C'<'e'd'o'N' 'r'o'f' 'p'o'r'D' '>'g'''''t's'i'L' ':'C'<'''' 'l'p'm'i'n'n' unsafe fn free(p: *mut Node<C>) {n dealloc(p as *mut u8, Self::layout_with_height((*p).''height));n }nn fn content_slice(&self) -> &[C::Item] {n // TODO: Use MaybeUninit::slice_get_ref ''w''hen it lands. This code is stolen from that implementation.nn // SAFETY: casting slice to a `*const [T]` is safe since the caller guarantees thatn // `slice` is initialized, and`MaybeUninit` is guaranteed to have the same layout as `T`.n // The pointer obtained is valid since it refers to memory owned by `slice` which is an // reference and thus guaranteed to be valid for reads.n let slice = &self.items[..self.num_items as usize];n unsafe { maybeinit_slice_get_ref(slice) }n }nn // The height is at least 1, so this is always valid.n fn first_skip_entry<'a>(&self) -> &'a SkipEntry<C> {n unsafe { &*self.nexts.as_ptr() }n }nn fn first_skip_entry_mut<'a>(&mut self) -> &'a mut SkipEntry<C> {n unsafe { &mut *self.nexts.as_mut_ptr() }n }nn // TODO: Rename to len() ?n fn get_userlen(&self) -> usize {n self.first_skip_entry().skip_usersizen }n n fn get_next_ptr(&self) -> *mut Node<C> {n self.first_skip_entry().noden }n}nnstruct NodeIter<'a, C: ListConfig>(Option<&'a Node<C>>);nimpl<'a, C: ListConfig> Iterator for NodeIter<'a, C> {n type Item = &'a Node<C>;nn fn next(&mut self) -> Option<&'a Node<C>> {n let prev = self.0;n if let Some(n) = self.0 {n *self = NodeIter(unsafe { n.first_skip_entry().node.as_ref() });n }n prevn }n}nn/// This is a set of pointers with metadata into a location in the list neededn/// to skip ahead, delete and insert in items. A cursor is reasonably heavyn/// weight - we fill in and maintain as many entries as the height of the listn/// dictates.n///n/// This is not needed for simply iterating sequentially through nodes and data.n/// For that look at NodeIter.n///n/// Note most/all methods using cursors are unsafe. This is because cursors usen/// raw mutable pointers into the list, so when used the following rules have ton/// be followed:n///n/// - Whenever a write happens (insert/remove/replace), any cursor not passed ton/// the write function is invalid.n/// - While a cursor is held the SkipList struct should be considered pinned andn/// must not be moved or deletedn#[derive(Copy, Clone)]npub struct Cursor<C: ListConfig> {n // TODO: Add a phantom lifetime reference to the skip list root for safety.nnn /// The global user position of the cursor in the entire list. This is usedn /// for when the max seen height increases, so we can populate previouslyn /// unused entries in the cursor and in the head node.n ///n /// This field isn't strictly necessary - earlier versions tacked this on ton /// the last item in entries... I'm still not sure the cleanest way to don /// this.n userpos: usize,nn /// When the userpos of an entry is 0 (totally valid and useful), a cursorn /// becomes ambiguous with regard to where exactly its pointing in then /// current entry. This is used to resolve that ambiguity.n local_index: usize,nn entries: [SkipEntry<C>; MAX_HEIGHT],n}nnimpl<C: ListConfig> Cursor<C> {n fn update_offsets(&mut self, height: usize, by: isize) {n for i in 0..height {n unsafe {n // This is weird but makes sense when you realise the nexts inn // the cursor are pointers into the elements that have then // actual pointers.n // Also adding a usize + isize is awful in rust :/n let skip = &mut (*self.entries[i].node).nexts_mut()[i].skip_usersize;n *skip = skip.wrapping_add(by as usize);n }n }n }nn /// Move a cursor to the start of the next node. Returns the new node (or an /// nullptr if this is the end of the list).n fn advance_node(&mut self) -> *mut Node<C> {n unsafe {n let SkipEntry { node: e, skip_usersize: offset } = self.entries[0];n // offset tells us how far into the current element we are (inn // usersize). We need to increment the offsets by the entry'sn // remaining length to get to the start of the next node.n let advance_by = (*e).get_userlen() - offset;n let next = (*e).get_next_ptr();n let height = (*next).height as usize;nn for i in 0..height {n self.entries[i] = SkipEntry {n node: next,n skip_usersize: 0n };n }nn for i in height..self.entries.len() {n self.entries[i].skip_usersize += advance_by;n }nn self.userpos += advance_by;n self.local_index = 0;nn nextn }n }nn fn is_at_node_end(&self) -> bool {n self.local_index == unsafe { (*self.here_ptr()).num_items } as usizen }nn fn advance_item(&mut self, height: u8) {n if self.is_at_node_end() { self.advance_node(); }n let usersize = C::get_usersize(unsafe { self.current_item() });nn for entry in &mut self.entries[0..height as usize] {n entry.skip_usersize += usersize;n }n self.userpos += usersize;n self.local_index += 1;n }nn fn advance_by_items(&mut self, num: usize, height: u8) {n for _ in 0..num { self.advance_item(height); }n }nn fn move_to_item_start(&mut self, height: u8, offset: usize) {n for entry in &mut self.entries[0..height as usize] {n entry.skip_usersize -= offset;n }n self.userpos -= offset;n }nn unsafe fn current_item(&mut self) -> &C::Item {n let node = &*self.here_ptr();n debug_assert!(node.num_items as usize >= self.local_index);n &*(node.items[self.local_index].as_ptr())n }nn /// Get the pointer to the cursor's current noden fn here_ptr(&self) -> *mut Node<C> {n self.entries[0].noden }n}nnimpl<C: ListConfig> PartialEq for Cursor<C> {n /// Warning: This returns false if one cursor is at the end of a node, andn /// the other at the start of the next node. Almost all code in this libraryn /// leaves cursors at the end of nodes, so this shouldn't matter too much inn /// practice.n fn eq(&self, other: &Self) -> bool {n if self.userpos != other.userposn || self.local_index != other.local_index {return false; }nn for i in 0..MAX_HEIGHT {n let a = &self.entries[i];n let b = &other.entries[i];n if a.node != b.node || a.skip_usersize != b.skip_usersize { return false; }n }n truen }n}nimpl<C: ListConfig> Eq for Cursor<C> {}nnimpl<C: ListConfig> fmt::Debug for Cursor<C> {n fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n f.debug_struct('Cursor')n ' /// Make a slice we can iterate from and steal''''' 'a't'a'd' from without droppingn //'''''''''''''''''''''':'' /// - If the iterator isn't fully drained then remaining items will ben /// forgotten ''''''''''''t'o'n' 'e'.' /// - The slice passed in here must be initialized or undefined behaviourn /// will hit us.'''r'a' 'y'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'s'u' 't'i'h' 'l'l'i'w' 'r'u'o'i'v'a'h'e'b' ''''''''''''' 's'e'u'l'a'v' 'd'e'n'i'f'e'd'n'u'''''''''''s'e'u'l'a'v' 'e'h't' 'r'o' ''''.'d'e'z'i'l'a'i't'i'n'i' 'e'b' 't's'u'm' 'e'r'e'h' 'n'i' 'd'e's's''''d'a'p' 'e'c'i'l's' 'e'h'T'e'h't'(not dropped)'' /// - If the ''''''''':':'e'z'i'''' -'s'u'''''''intrinsic'''unchecked_sub''(x: T, y: T)'''','''''''h'c'n'u':':'s'''''r't'n'i':':'d't's''''''''l'd'e'k'c'n'u'iterator isn't fully drained then remaining items'''''''' 'e'b' 'l'l'i'w' are forgottenn /// (not dropped)'e'f'a's'n'''''''' 'e'h't' 'f'I'u' 'y'r'e'v' '''''''''''''''''''''''''''''''''''''''''''''''''')'d'e'p'p'o'r'd' 't'o'n'(' 'n'e't't'o'g'r'o'f' 'e'r'a' 's'm'e't'i' 'g'n'i'n'i'a'm'''''''m'a'e'r''''' 'e'h't' 'n'e'h't' 's'i' 's'i'h'T'/ content. Its unsafe if:n ///n /// - The iterator isn't fully drained (then we might not drop contents)n /// - The contents we iterate over aren't initializedn ///' .field('userpos', &self.userpos)n .f'''''''''''''''''''''''''t'n'e't'n'o'c' 'g'n'i'p'p'o'r'd' 't'u'o'h't'i'w' 'ield('local_index', &self.local_index)n .finish()n }n}nn// None of the rust builtins give me what I want, which is a copy-free iteratorn// to owned items in a MaybeUninit array. Eh; its easy enough to make my '''''' ':'O'D'O'T'''own.nstru'''''''''''''''f'e'r'_'t'e'g'_'e'c'i'l's':':'ct UninitOwned''''''''''''''''''''''''.'e'l'b'a'l'i'a'v'a''''''''''e'l'b'a'i'l'a'v'a' 'n'e'h'w' 'e'c'a'l'p'e'R' '''Iter<'a, C: ListConfig> {n // Based on the core slice IterMut implementation.n ptr: NonNull<C::Item>,n end: *mut C::Item,n _marker: PhantomData<&'a SkipList<C>>n}nnimpl<'a, C: ListConfig> UninitOwnedIter<'a, C> {n /// Make a slice we can iterate from and steal from. Its'' ''unsafe if:n /// n /// - The iterator isn't fully drained (then we might not drop conten'''Skip'ts)n /''//'' - The con''t''e''X'''MAX'nts we iterate over aren't initializedn /// n /// After iterating, the contents are uninit memory.n unsafe fn from_slice(slice: &[MaybeUninit<C::Item>]) -> Self {n let ptr = sli'SkipEntr'''new_null('''MAX_HEIGHT''''X'A''''X'M' ';')':':'y'''''p'i'k'S'ce.as_ptr() as *mut C::Item; // Safe.n let end = ptr.add(slice.len());nn UninitOwnedIter {n ptr: NonNull::new_unchecked(ptr),n end,n _marker: PhantomDatan }n ''''''''''''e'c'i'l's'_'t''''_''''''''''''''''i'l's')''n ''''' 'n'f' 'n ' '}n // unsafe fn from_slice(slice: &[C::Item]) -> Self {n // unsafe {n // let ptr = slice.as_mut_ptr();n // let end = ptr.add(slice.len());nn // UninitOwnedIter {n // ptr: NonNull::new_unchecked(ptr),n // end,n // _marker: PhantomDatan // }n // }n // }n}nnimpl<'a, C: ListConfig> Iterator for UninitOwnedIter<'a, C> {n type Item = C::Item;nn fn next(&mut self) -> Option'n ''''''''''''''''''''n '''''''''''''''''''{' 'e'f'a's'n'u' '''Non'''''n '''''''''''''''' 'e'v'o'm'e'R' ':'O'D'O'T' '/''''''' ';'/' 'Nul'''new_unchecked''''''(ptr''}' ': *mut T)':':'l''')''''''l'u'N'n'o'N' ''''''''''''''''''')'('r't'p'_'s'a'.'''''''''(')''t'e's'f'f'o'.'r't'p'.'f'l'e's'''''';'1' '='+' 'r't'p'.'f'l'e's' ';'r't'p'.'f'l'e's' '=' 'r't'''p' 't'e'l' '<Self::Item> {n if self.ptr.as_ptr() == self.end {n Nonen } else {n Some(unsafe { self.ptr.as_'''n ''''''''''''''''''''''''''''''''''''''''''''''''' ''''''''''''('''''''''''''''''''''''''''''''''''')'('r't'p'_'s''''':':'m'e'm''a'.'''''''''''''''''''''''''''''''''''':':'''''n '''''''''''''''''')')'e'z'i's'('e'm'o'S' ','e'z'i's'(' ';')'('>'m'e't'I':':'C'<':':'f'o'_'e'z'i's' '/' ''''.')'''e'z'i's'u' 's'a' 'r't'p'.'f'l'e's' '-' 'e'z'i's'u' 's'a' 'd'n'e'.'f'l'e's''''''''''''''''''('b'u's'.''''''')'''''''''''''as_ptr()'''s'a'.'';'r't'p'.'f'l'e's' '-' 'd'n'e'.'f'l'e's' '=' 'e'z''''e'i's' 't'e'l' '''''' }''n 'n ' ' '{' ')'>'e'z'i's'u'<'n'o'i't'p'O' ','e'z'i'''''''i'e's'u'(' '>'-' ')'f'l'e's'&'('t'n'i'h'_'e'z'i's'''''''z'i' 'n'f' 'n ' 'ptr().read() })n }n }n}nn// TODO: Stolen from MaybeUninit::uninit_array. Replace with the real uninit_array when stable.n#[inline(always)]nfn uninit_items_array<T>() -> [MaybeUninit<T>; NODE_NUM_ITEMS] {n unsafe { MaybeUninit::<[MaybeUninit<T>; NODE_NUM_ITEMS]>::uninit().assume_init() }n}nn// Stolen from core::mem::MaybeUninit. Its just not standardized yet.n#[inline(always)]nunsafe fn maybeinit_slice_get_ref<T>(slice: &[MaybeUninit<T>]) -> &[T] {n // SAFETY: casting slice to a `*const [T]` is safe since the caller guarantees thatn // `slice` is initialized, and`MaybeUninit` is guaranteed to have the same layout as `T`.n // The pointer obtained is valid si'''''''' 't'u'm''''''t'u'm'_''nce it refers to memory owned by `slice` which is an // reference and thus guaranteed to be valid for reads.n &*(slice as *const [MaybeUninit<T>] as *const [T])n}nnnimpl<C: ListConfig> SkipList<C> {n pub fn new() -> Self {n SkipList::<C> {n num_items: 0,n num_usercount: 0,n rng: None,n head: Node {n items: uninit_items_array(),n num_items: 0,n height: 1, // Stores max height of list nodesn parent: ptr::null_mut(),n nexts: [],n },n _nexts_padding: [SkipEntry::new_null(); MAX_HEIGHT],n }n }nn pub fn init_rng_from_seed(&mut self, seed: u64) {n self.rng = Some(SmallRng::seed_from_u64(seed));n }nn fn get_rng(&mut self) -> &mut SmallRng {n // I'm sure there's a nicer way to implement this.n if self.rng.is_none() {n // We'll use a stable RNG in debug mode so the tests are stable.n if cfg!(debug_assertions) {n self.init_rng_from_seed(123);n } else {n self.rng = Some(SmallRng::from_entropy());n }n }n self.rng.as_mut().unwrap()n }nn pub fn new_from_slice(s: &[C::Item]) -> Self where C::Item: Copy {n let mut rope = Self::new();n rope.insert_at(0, s);n ropen }nn pub fn get_userlen(&self) -> usize {n self.num_usercountn }nn fn iter(&self) -> NodeIter<C> { NodeIter(Some(&self.head)) }n n pub fn len_items(&self) -> usize {n self.num_items as usizen }nn fn heads_mut(&mut self) -> &mut [SkipEntry<C>] {n unsafe {n std::slice::from_raw_parts_mut(self.head.nexts.as_mut_ptr(), self._nexts_padding.len())n }n }nn fn is_head(&self, node: *const Node<C>) -> bool {n node as *const _ == &self.head as *const _n }nn /// Walk the list and validate internal constraints. This is used forn /// testing the structure itself, and should generally not be called byn /// users.n pub fn check(&self) {n // #[cfg(test)]n {n // self.print();n assert!(self.head.height >= 1);n assert!(self.head.height <= MAX_HEIGHT_U8);nn let head_ptr = &self.head as *const _ as *mut _;n // let skip_over = self.get_top_entry();n // println!('Skip over skip chars {}, num bytes {}', skip_over.skip_items, self.num_bytes);nn let mut prev: [*const Node<C>; MAX_HEIGHT] = [ptr::null(); MAX_HEIGHT];nn let mut iter = [SkipEntry {n // Bleh.n node: head_ptr,n // The skips will store the total distance travelled since then // start of this traversal at each height. All the entries aboven // head.height are ignored though.n skip_usersize: 0n }; MAX_HEIGHT];nn let mut num_items = 0;n let mut num_usercount = 0;nn for (_i, n) in self.iter().enumerate() {n // println!('visiting {:?}', n.as_str());n if !self.is_head(n) { assert!(n.num_items > 0); }n assert!(n.height <= MAX_HEIGHT_U8);n assert!(n.num_items as usize <= NODE_NUM_ITEMS);nn // Make sure the number of items matches the countn let local_count = C::userlen_of_slice(n.content_slice());n assert_eq!(local_count, n.get_userlen());nn let expect_parent = if self.is_head(n) {n ptr::null() // The head's parent is nulln } else if n.height == self.head.height {n &self.head as *const _ // Max height nodes point back to headn } else {n prev[n.height as usize]n };nn // println!('visiting {} {:?}', i, n as *const _);n // dbg!(n as *const _);n // dbg!((n as *const _, (*n).height));n // dbg!(n.parent);n // dbg!(&self.head as *const _);nn assert_eq!(n.parent as *const _, expect_parent, 'invalid parent');n n for (i, entry) in iter[0..n.height as usize].iter_mut().enumerate() {n assert_eq!(entry.node as *const _, n as *const _);n assert_eq!(entry.skip_usersize, num_usercount);nn // println!('replacing entry {:?} with {:?}', entry, n.nexts()[i].node);n prev[i] = n;n entry.node = n.nexts()[i].node;n entry.skip_usersize += n.nexts()[i].skip_usersize;n }nn num_items += n.num_items as usize;n num_usercount += n.get_userlen();nn // Check the value returned by the iterator functions matches.n let (mut normal_iter, local_offset) = self.iter_at_userpos(num_usercount);n assert_eq!(local_offset, 0);nn // Dirty hack. If n has 0-sized elements at the end, the normaln // cursor won't be at the end...n while normal_iter.here_ptr() != n as *const _ as *mut _ {n normal_iter.advance_node();n }n normal_iter.local_index = n.num_items as usize;n let node_iter = unsafe { self.iter_at_node(n, n.get_userlen(), n.num_items as usize) };n assert_eq!(normal_iter, node_iter);n }nn for entry in iter[0..self.head.height as usize].iter() {n // println!('{:?}', entry);n assert!(entry.node.is_null());n assert_eq!(entry.skip_usersize, num_usercount);n }n n // println!('self bytes: {}, count bytes {}', self.num_bytes, num_bytes);n assert_eq!(self.num_items, num_items);n assert_eq!(self.get_userlen(), num_usercount);n }n }n n n /// Internal function for creating a cursor at a particular location in then /// skiplist. The returned cursor contains list of nodes which point pastn /// the specified position, as well as offsets of how far into theirn /// character lists the specified characters are.n ///n /// Sometimes a call to iter_at_userpos is ambiguous:n ///n /// - The item can contain items with zero usersize. The cursor could pointn /// to any of them.n /// - If the location is at the end of a node, it is equally valid to returnn /// a position at the start of the next node.n ///n /// Because its impossible to move backwards in the list, iter_at_userposn /// returns the first admissible location with the specified userpos.n /// n /// Returns (cursor, offset into the specified item).n ///n /// TODO: This should be Pin<&self>.n fn iter_at_userpos(&self, target_userpos: usize) -> (Cursor<C>, usize) {n assert!(target_userpos <= self.get_userlen());nn let mut e: *const Node<C> = &self.head;n let mut height = self.head.height as usize - 1;n n let mut offset = target_userpos; // How many more items to skipnn // We're populating the head node pointer to simplify the case when then // iterator grows. We could put offset into the skip_usersize but itn // would only be *mostly* correct, not always correct. (Since cursorn // entries above height are not updated by insert.)n let mut cursor = Cursor {n entries: [SkipEntry {n node: &self.head as *const _ as *mut _,n skip_usersize: usize::MAXn }; MAX_HEIGHT],n local_index: 0,n userpos: target_userpos,n };nn loop { // while height >= 0n let en = unsafe { &*e };n let next = en.nexts()[height];n let skip = next.skip_usersize;n if offset > skip {n // Go right.n debug_assert!(e == &self.head || en.num_items > 0);n offset -= skip;n e = next.node;n assert!(!e.is_null(), 'Internal constraint violation: Reached rope end prematurely');n } else {n // Record this and go down.n cursor.entries[height] = SkipEntry {n skip_usersize: offset,n node: e as *mut Node<C>, // This is pretty grossn };nn if height == 0 { break; } else { height -= 1; }n }n };nn // We should always land within the node we're pointing to.n debug_assert!(offset <= unsafe { &*cursor.here_ptr() }.get_userlen());nn // We've found the node. Now look for the index within the node.n let en = unsafe { &*e };n let mut index = 0;nn while offset > 0 {n assert!(index < en.num_items as usize);n n let usersize = C::get_usersize(unsafe { &*en.items[index].as_ptr() });n if usersize > offset { break; } // We're in the middle of an item.n offset -= usersize;n index += 1;n }n cursor.local_index = index;nn (cursor, offset)n }nn unsafe fn iter_at_node(&self, n: *const Node<C>, mut offset: usize, local_index: usize) -> Cursor<C> {n let mut n = n as *mut Node<C>; // We don't mutate, but we need a mut ptr.nn let mut cursor = Cursor {n userpos: 0, // We'll set this later.n local_index: local_index,n entries: [SkipEntry {n node: &self.head as ''*const _ as *mut _,n skip_usersize: usize::MAXn }; MAX_HEIGHT],n };nn let mut h = 0;n loop {n while h < (*n).height as usize {n cursor.entries[h] = SkipEntry {n '' node: n,n skip_usersize: offsetn };nn h += 1;n }nn let parent = (*n).parent;n // Reached the head.n if parent.is_null() { break; }nn // If we're the same height as the parent its fine.n debug_assert!((*parent).height as usize > hn || (self.is_head(parent) && (*parent).height as usize == h));nn // Walk from parent back to n, figuring out the offset.n let mut c = parent;n // let walk_height = (*parent).height as usize - 2;n let walk_height = (*n).height as usize - 1;n while c != n {n let elem = (*c).nexts()[walk_height];n offset += elem.skip_usersize;n c = elem.node;n }nn n = parent;n }nn cursor.userpos = offset;n cursorn }nn pub fn iter_at_marker(&mut self, marker: ItemMarker<C>, query: &<C::Item as Queryable>::Query) -> Cursor<C> where C::Item: Queryable {n // The marker gives us a pointer into a node. Find the item.n unsafe {n let n = marker.ptr;nn let mut offset: usize = 0;n let mut local_index = None;n for (i, item) in (*n).content_slice().iter().enumerate() {n if let Some(item_offset) = item.contains_item(query) {n offset += item_offset;n local_index = Some(i);n break;n } else {n offset += C::get_usersize(item);n }n }nn let local_index = local_index.expect('Invalid marker - item not found in node');n self.iter_at_node(n, offset, local_index)n }n }nn // Internal fn to create a new node at the specified iterator filled withn // the specified content. The passed cursor should point at the end of then // previous node. It will be updated to point to the end of the newlyn // inserted content.n // ''unsafe fn insert_node_at(&mut self, curs'>'''or: '// '&mut Cursor<C'('''>'''''''''''''''('!'g'b'd', contents: ''')'<''''&[C::Item], new_userlen: usize, move_cursor: bool) {n unsafe fn insert_node_at<Notify, I>(&mut self, cursor: &mut Cursor<C>, contents: &mut I, num_items: usize, move_cursor: bool, notify: &mut Notify)n where Notify: FnMut(&[C::Item], ItemMarker<C>), I: Iterator<Item=C::Item> {nn // println!('Insert_node_at {} len {}', contents.len(), self.num_bytes);n // debug_assert_eq!(new_userlen, C::userlen_of_slice(contents));n assert!(num_items <= NODE_NUM_ITEMS);n debug_assert!(contents.size_hint().0 >= num_items);nn let new_node_ptr = Node::alloc(self.get_rng());n let new_node = &mut *new_node_ptr;n // let num_items = contents.len();n new_node.num_items = num_items as u8;nn for (slot, item) in new_node.items[..num_items].iter_mut().zip(contents) {n (slot.as_mut_ptr() as *mut C::Item).write(item); // Write makes sure we don't drop the old value.n }n // new_node.items[..contents.len()].copy_from_slice(contents);nn let new_userlen = C::userlen_of_slice(new_node.content_slice());nn let new_height = new_node.height;n let new_height_usize = new_height as usize;nn let mut head_height = self.head.height as usize;n while head_height < new_height_usize {n // This seems weird given we're about to overwrite these valuesn // below. What we're doing is retroactively setting up the cursorn // and head pointers *as if* the height had been this high alln // along. This way we only have to populate the higher head valuesn // l''azily.n let total_userlen = self.num_usercount;n let nexts = self.heads_mut();n nexts[head_height].skip_usersize = total_userlen;n cursor.entries[head_height].skip_usersize = cursor.userpos;nn head_height += 1; // This is ugly.n self.head.height += 1;n }nn new_node.parent = if new_height_usize == MAX_HEIGHT {n &self.head as *const _ as *mut _n } else { cursor.entries[new_height_usize].node };nn for i in 0..new_height_usize {n let prev_skip = &mut (*cursor.entries[i].node).nexts_mut()[i];n let new_nexts = new_node.nexts_mut();nn // The new node points to the successor (or null)n new_nexts[i] = SkipEntry {n node: prev_skip.node,n skip_usersize: new_userlen + prev_skip.skip_usersize - cursor.entries[i].skip_usersizen };nn // The previous node points to the new noden *prev_skip = SkipEntry {n node: new_node_ptr,n skip_usersize: cursor.entries[i].skip_usersizen };nn // Move the iterator to the end of the newly inserted node.n if move_cursor {n cursor.entries[i] = SkipEntry {n no''''''''''''''''''''''''''''''i' 'y'l'i'r'a's's'e'c'e'''n' 't'''n's'e'o'd' '''m'e't'I'''de: new_node_ptr,n skip_usersize: new_userlenn };n }n }nn for i in new_height_usize..head_height {n (*cursor.entries[i].node).nexts_mut()[i].skip_usersize += new_userlen;n if move_cursor ''{n cursor.entries[i].skip_usersize += new_userlen;n }n }nn // Update parents.n if new_height_usize > 1 {nn let mut n = new_node_ptr;n let mut skip_height = 0;nn loop {n n = (*n).nexts_mut()[skip_height].node;n if n.is_null() || (*n).height >= new_height { break; }n n (*n).parent = new_n''o''de_ptr;n skip_height = usize::max(skip_height, (*n).height as usize - 1);n }n }n n self.num_items += num_items;n self.num_usercount += new_userlen;n if move_cursor {n cursor.userpos += new_userlen;n cursor.local_index = num_items;n }nn notify(new_node.content_slice(), ItemMarker {n ptr: new_node_ptr,n _phantom: PhantomDatan });n }nn // unsafe fn insert_at_iter(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item]) {n unsafe fn insert_at_iter<Notify, I>(&mut self, cursor: &mut Cursor<C>, contents: &mut I, notify: &mut Notify)n where Notify: FnMut(&[C::Item], ItemMarker<C>), I: ExactSizeIterator<Item=C::Item> {n // iter specifies where to insert.nn let mut e = cursor.here_ptr();nn // The insertion offset into the de''stination node.n assert!(cursor.userpos <= self.num_usercount);n assert!(cursor.local_index <= (*e).num_items as usize);nn '_''' // We might be able to insert the new data into the current node, depending onn // how big it is.n let num_inserted_items = contents.len();n // let num_inserted_usercount = C::userlen_of_slice(contents);nn // Can we insert into the current node?n let mut insert_here = (*e).num_items as usize + num_inserted_items <= NODE_NUM_ITEMS;nn // Can we insert into the start of the successor node?n if !insert_here && cursor.local_index == (*e).num_items as usize && num_inserted_items <= NODE_NUM_ITEMS {n // We can insert into the subsequent node'_' if:n // - We can't insert into the current noden // - There _is_ a next node to insert inton // - The insert would be at the start of the next noden // - There's room in the next noden if let Some(next) = (*e).first_skip_entry_mut().node.as_mut() {n if next.num_items as usize + num_inserted_items <= NODE_NUM_ITEMS {n cursor.advance_node();n e = next;nn insert_here = true;n }n }n }nn let item_idx = cursor.local_index;n let e_num_items = (*e).num_items as usize; // convenience.nn if insert_here {n // println!('insert_here {}', contents);n // First push the current items later in the arrayn let c = &mut (*e).items;n if item_idx < e_num_items {n // Can't use copy_within because we aren't sure if the typen // implements Copy. Memmove the existing items.n ptr::copy(n &c[item_idx],n &mut c[item_idx + num_inserted_items],n (*e).num_items as usize - item_idx);n // c[..].copy_within(item_idx..e_num_items,n // item_idx + num_inserted_items);n }nn // Then copy in the new items. Can't memcpy from an iterator, butn // the optimizer should make this fast.n let dest_content_slice = &mut c[item_idx..item_idx + num_inserted_items];n for (slot, item) in dest_content_slice.iter_mut().zip(contents) {n // Do not drop the old items - they w''ere only moved.n slot.as_mut_ptr().write(item);n }n let dest_content_slice = maybeinit_slice_get_ref(dest_content_slice);n // c[item_idx..item_idx + num_inserted_items].copy_from_slice(contents);nn (*e).num_items += num_inserted_items as u8;n self.num_items += num_inserted_items;n let num_inserted_usercount = C::userlen_of_slice(dest_content_slice);n self.num_usercount += num_inserted_usercount;nn // .... aaaand update all the offset amounts.n cursor.update_offsets(self.head.height as usize, num_inserted_usercount as isize);nn // Usually the cursor will be discarded after one change, but forn // consistency of compound edits we'll update the cursor to point ton // the end of the new content.n for entry in cursor.entries[0..self.head.height as usize].iter_mut() {n entry.skip_usersize += num_inserted_usercount;n }n cursor.userpos += num_inserted_usercount;n cursor.local_index += num_inserted_items;nn notify(dest_content_slice, ItemMarker {n ptr: e,n _phantom: PhantomDatan });n } else {n // There isn't room. We'll need to add at least one new node to then // list. We could be a bit more careful here and copy as much asn // possible into the current node - that would decrease the numbern // of new nodes in some cases, but I don't think the performancen // difference will be large enough to justify the complexity.nn // If we're not at the end of the current node, we'll need to removen // the end of the current node's data and reinsert it later.n let num_end_items = e_num_items - item_idx;nn let (end_items, end_usercount) = if num_end_items > 0 {n // We'll mark the items as deleted from the node, while leavingn // the data itself there for now to avoid a copy.nn // Note that if we wanted to, it would also be correct (andn // slightly more space efficient) to pack some of the newn // string's characters into this node after trimming it.n let end_items = &(*e).items[item_idx..e_num_items];n (*e).num_items = item_idx as u8;n let end_usercount = (*e).get_userlen() - cursor.entries[0].skip_usersize;nn cursor.update_offsets(self.head.height as usize, -(end_usercount as isize));nn // We need to trim the size off because we'll add the charactersn // back with insert_node_at.n self.num_usercount -= end_usercount;n self.num_items -= num_end_items;nn (Some(end_items), end_usercount)n } else {n (None,'' 0)n };nn // Now we insert new nodes containing the new character data. Then // data is broken into pieces with a maximum size of NODE_NUM_ITEMS.n // As further optimization, we could try and fit the last piece inton // the start of the subsequent node.n let mut items_remaining = num_inserted_items;n while items_remaining > 0 {n let insert_here = usize::min(items_remaining, NODE_NUM_ITEMS);n self.insert_node_at(cursor, contents, insert_here, true, notify);n items_remaining -= insert_here;n }n // for chunk in contents.take(NODE_NUM_ITEMS) {n // // let userlen = C::userlen_of'''''')'('n'e'l'.'_'''''''''s'm'e't'i'_'d'n'e'slice(chunk);n // self.insert_node_at(cursor, chunk, true, notify);n // }nn // TODO: Consider recursively calling insert_at_iter() here insteadn // of making a whole new node for the remaining content.n if let Some(end_items) = end_items {n // Passing false to indicate we don't want the cursor updatedn // after this - it should remain at the end of the newlyn // inserted content, which is *before* this end bit.n self.insert_node_at(cursor, &mut UninitOwnedIter::<C>::from_slice(end_items), end_usercount, false, notify);n }n }n }nn // unsafe fn insert_at_iter(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item]) {n // self.insert_at_iter_and_notify(cursor, contents, Self::no_notify);n // }nn /// Interestingly unlike the original, here we only care about specifyingn /// the number of removed items by counting them. We do not use usersize inn /// the deleted item count.n ///n /// If the deleted content occurs at the start of a node, the cursor passedn /// here must point to the end of the previous node, not the start of then /// current node.n '' unsafe fn del_at_iter(&mut self, cursor: &mut Cursor<C>, mut num_deleted_items: usize) {n if num_deleted_items == 0 { return; }nn let mut item_idx = cursor.local_index;n let mut e = curso''r''.here_ptr();n while num_deleted_items > 0 {n // self.print();n // if cfg!(debug_assertions) { self.check(); }n if item_idx == (*e).num_items as usize {n let entry = (*e).first_skip_entry();n // End of current node. Skip to the start of the next one. We'ren // intentionally not updating the iterator because if we deleten // a whole node we need the iterator to point to the previousn // element. And if we only delete here, the iterator doesn'tn // need to be moved.n e = entry.node;n if e.is_null() { panic!('Cannot delete past the end of the list'); }n item_idx = 0;n }nn let e_num_items = (*e).num_items as usize;n let removed_here = min(num_deleted_items, e_num_items - item_idx);n n let height = (*e).height as usize'';n let removed_userlen;nn if removed_here < e_num_items || e as *const _ == &self.head as *const _ {n // Just trim the node down.n let trailing_items = e_num_items - item_idx - removed_here;n n let c = &mut (*e).items;n removed_userlen = C::userlen_of_slice(maybeinit_slice_get_ref(&c[item_idx..item_idx + removed_here]));n if trailing_items > 0 {n ptr::copy(n &c[item_idx + removed_here],n &mut c[item_idx],n trailing_items);n // c[..].copy_within(item_idx + removed_here..e_num_items, item_idx);n }nn (*e).num_items -= removed_here as u8;n self.num_items -= removed_here;n self.num_usercount -= removed_userlen;nn for s in (*e).nexts_mut() {n s.skip_usersize -= removed_userlen;n }n } else {n // Remove the node from the skip list entirely. e should be then // next node after the position of the iterator.n assert_ne!(cursor.here_pt''r(), e);nn 't<I>''''<''''<t'''''''>'I'<'t''''''<' ''''''e'c'i'l's'_'''''T'mu' 't'>'''''>'I'''''''>''I'T'''''''' 't'u'm''<' where I: ExactSizeIterator<Item=C::Item>'' where C::Item: Copy''&[C::Item]'' removed_use'I'rlen = (*e).get_userlen();n' where I: ExactSizeIterator<Item=C::Item>' '&[C::Item]' where C:'' }'n ':Item: Copy'n le''num_inserted_item' ''inserted_conten'.len();'t' insert'='s' num_inserted_ite't'''n pub fn replace_at(&mut self, mut start_userpos: usize, removed_item''''''' ''n ' if cfg!(debug_assertions) {n let (mut c2, _) = self.iter_at_userpos(userpos);n c2.advance_by_items(plus_items, self.head.height);n assert_eq!(cursor, &c2);n }n' 'n ' 's: usize, inserted''_content: &[C::Item'''n '''''''n'''mut '''um_inserted_ite''num_inserted_item''''''''insert''inserted_co'.iter().copied()'num_inserted_items'''n self'replace_at'start_userpos'(mut start_userpos: usize,'remov'iter().copied());'ed_items' removed_items: usize,'inserted_content.slic' mut inserted_content: I)'.repl'num_''nten''''''''';')'('n'e'l'.'t'''''''t'r'e's'n'i' '=' 's'''''''''''''''''e't'i'_'d'e't'r'e's'n'i'_'m'u'n' 't'e'l' ']) where C'''' ''''' '' 'n if cfg!(debug_assertions) {n let (mut c2, _) = self.'''''''n 'n pub fn replace_at_slice(&mut self, mut start_userpos: usize, removed_items: usize, inserted_content: &[C::Item]) where C::Item: Copy {n }' 'n ' '''i' ''''' '''n'ter_at_userpos(userpos);n 'inserted_content.len()''num_' c2.advance_by_items(plus_items, self.head.height);n assert_eq!(cursor, &c2);n }n'n'''''''' ''n ' if cfg!(debug_assertions) {n let (mut c2, _) = self.iter_at_userpos(userpos);n c2.advance_by_items(plus_items, self.head.height);n assert_eq!(cursor, &c2);n }n' 'n ' '::Item: Copy {''''n pub fn replace_at(&mut self, mut st'mut '''''art_userpos: usize, removed_''items: usize, inserted_content: &[C::Item]) wher'num_insert''ed_items'''n 'repl' '''''''mut start_userpos: usize'replace_at''''''removed_items: usize'''''''''s'''''''mut inserted_content: I'''''''''s'''''''''slic)'''''''''''''''''''''''''''';')')'('d'e'i'p'o'c'.')'('r'e't'i'''''c'i'l's'.'t'n'e't'n'o'c'_'d'e't'r'e's'n'i'm'e't'i'_'d'e'v'o'm'e'r'o'p'r'e's'u'_'t'r'a't's'(mut start_userpos: usize, removed_items: usize, mut inserted_content: I)'''''l'p'e'r'.'f'l'e's' ''''_'m'u'n'e C::Item: Copy {'' let next = (*e).firs'I't_skip_entr' where I: ExactSizeIterator<Item=C::Item>'y().node;nn // println!('removing {:?} contents {:?} height {}', e, (*e).content_slice(), height);nn for i in 0..height {n let s = &mut (*cursor.entries[i].'''''''n 'n pub fn replace_at_slice(&mut self, mut start_userpos: usize, removed_items: usize, inserted_content: &[C::Item]) where C::Item: Copy {n }' 'n ' 'node).nexts_mu''t()[i];n s.node = (*e).nexts_mut()[i].node;n s.skip_usersize += (*e).nexts()[i].skip_usersize - removed_userlen;n }nn self.''n''um_items -= (*e).num_items as usize;n self.num_usercount -= removed_userlen;nn // Update parents.n if height > 1 {n let mut n = e;n // let new_parent = cursor.entrie''s[height - 1].node;nn // If you imagine this node as a big building, we need ton // update the parent of all the nodes we cast a shadow over.n // So, if our height is 3 and the next nodes have heights 1n // and 2, they both need new parents.n let mut parent_height = 1;n let cursor_node = cursor.here_ptr();n let cursor_node_height = (*cursor_node).height as usize;n let mut new_parent = if height >= cursor_node_height {n cursor.entries[parent_height].noden } else {n cursor_noden };nn loop {n // dbg!(skip_height);n // dbg!((*n).height as usize);nn n = (*n).nexts_mut()[parent_height - 1].node;n if n.is_null() || (*n).height >= height as u8 { break; }n let n_height = (*n).height as usize;nn '' // dbg!((*n).content_slice());n // dbg!((*n).height);n n assert_eq!((*n).parent, e);n assert!(n_height >= parent_heig'''' 't'u'm''''n'ht - 1)'''>'I'<';nn if n_heig'I'ht > p'''C::Item: Copy, '''ar'n '''''num_inserted_item'''''''''''''''''';')'('n'e'l'.'s't'n'e't'n'o'c' '=' 's'''''''''''t'r'e's'n'i'_'m'u'n' 't'e'l' 'ent_height ''' I: ExactSizeIterator<Item=C::Item>' ','{n parent_height = n_height;n if n_height >= cursor_node_height {n new_parent = cursor.entries[parent_hei'num_inserted_items''num_''contents.len()''num_''num_inserted_items'''''_'m'u'n'ght].noden }n'contents' 'contents.iter().copied()'''''''''s't'n'e't'n'o'c' }n n (*n).parent = new_parent;n }n }nn Node::free(e);n e = next;n }nn for i in height..self.head.height as usize {n let s = &mut (*cursor.entries[i].node).nexts_mut()[i];n s.skip_usersize -= removed_userlen;n }nn num_deleted_items -= removed_here;nn // if cfg!(debug_assertions) { self.check(); }n }n }nn // unsafe fn insert_at_iter<Notify>(&mut self, cursor: &mut Cursor<C>, contents: &[C::I'contents'tem], mut notify: Notify)n 'contents.iter().copied()'// wher'num_inserted_items'e 's'N't'o'n't'e'num_''i't'f'contents.len()''n'y'o': FnMut(&[C::'num_'Item],'num_inserted_items' Item'_'M'm'''u'c'arker<C>) {nn'n' unsafe fn replace_at_iter<Notify, I>(&mut self, cursor: &mut Cursor<C>, mut removed_items: usize, inserted_content: &mut I, mut notify: Notify)n where Notify: FnMut(&[C::Item], ItemMarker<C>), I: ExactSizeIterator<Item=C::Item> {n if removed_items == 0 && inserted_content.len() == 0 { return''; }nn // Replace as many items from removed_items as we ca' ''''''inser''''''''''''''''''''''''''''''''''';')')'('d'e'i'p'o'c'.')'('r'e't'i'.'s't'n'e't'n'o'c''''''' ','s'o'p'r'e's'u'('t'a'_'t''insert_at_iter(cursor: &mut Cursor<C>, contents: &mut I, notify: &mut Notify)'''''''t'r'e's'n'i'.'f'l'e's' 'n with inserted_content.n let mut replaced_items = min(removed_items, inserted_content.len());n '''n 'pub fn insert_a''''''e'c'i'l's'_'t(&mut self, mut userpos: usize, contents: &[C::Item]) where '''''' ''' }''n 'n ' '{'''' ' 'C::Item: Copy' 'n ' 'removed_items -= replaced_items;nn while replaced_items > 0 {n debug_assert!(inserted_content.len() >= replaced_items);n let mut e = cursor.here_ptr();n if cursor.local_index == (*e).num_items as usize {n '' // Move to the next item.n e = cursor.advance_node();n if e.is''_null() { panic!('Cannot replace past the end of the list'); }n }nn let index = cursor.local_index;nn let e_num_items = (*e).num_items as usize;n let replaced_items_here = min(replaced_items, e_num_items - index);nn let dest = &mut (*e).items[index..index + replaced_items_here];n let old_usersize = C::userlen_of''_slice(maybeinit_slice_get_ref(dest));nn // Replace the items themselves. Everything else is commentary.n // Would prefer to use zip() but it wants ownership of inserted_content :/n for slot in dest.iter_mut() {n *slot.as_mut_ptr() = inserted_content.next().unwrap();n }n // for (slot, item) in dest.iter_mut().zip(inserted_content) {n // *slot.as_mut_ptr() = item; // Drop the replaced content.n // }nn let dest = maybeinit_slice_get_ref(dest);n let new_usersize = C::userlen_of_slice(dest);n let usersize_delta = new_usersize as isize - old_usersize as isize;nn // old_items.copy_from_slice(new_items);nn if usersize_delta != 0 {n cursor.update_offsets(self.head.height as usize, usersize_delta)n }n // I hate this.n self.num_usercount = self.num_usercount.wrapping_add(usersize_delta as usize);nn // inserted_content = &inserted_content[replaced_items_here..];n replaced_items -= replaced_items_here;n // We'll hop to the next Node at the start of the next loopn // iteration if needed.n cursor.local_index += replaced_items_here;nn for i in 0..self.head.height as usize {n cursor.entries[i].skip_usersize += new_usersize;n }n cursor.userpos += new_usersize;nn notify(dest, ItemMarker {n ptr: e,n _phantom: PhantomData,n });n }nn // Ok now one of two things must be true. Either we've run out ofn // items to remove, or we've run out of items to insert.n if inserted_content.len() > 0 {n // Insert!n debug_assert!(removed_items == 0);n self.insert_at_iter(cursor, inserted_content, &mut notify);n } else if removed_items > 0 {n self.del_at_iter(cursor, removed_items);n }n }nn fn dbg_check_cursor_at(&self, cursor: &Cursor<C>, userpos: usize, plus_items: usize) {n if cfg!(debug_assertions) {n // let (mut c2, _) = self.iter_at_userpos(userpos);n let (mut c2, _) = self.iter_at_userpos(userpos);n c2.advance_by_items(plus_items, self.head.height);n assert_eq!(cursor, &c2);n }n }nn fn no_notify(_items: &[C::Item], _marker: ItemMarker<C>) {}nn pub fn replace_at(&mut self, mut start_userpos: usize, removed_items: usize, inserted_content: &[C::Item]) where C::Item: Copy {n start_userpos = min(start_userpos, self.get_userlen());nn let (mut cursor, offset) = self.iter_at_userpos(start_userpos);n assert_eq!(offset, 0, 'Splitting nodes not yet supported');nn unsafe { self.replace_at_iter(&mut cursor, removed_items, &mut inserted_content.iter().copied(), Self::no_notify); }nn if cfg!(debug_assertions) {n let (mut c2, _) = self.iter_at_userpos(start_userpos);n c2.advance_by_items(inserted_content.len(), self.head.height);n if &cursor != &c2 { panic!('Invalid cursor after replace'); }n }n }nn pub fn insert_at(&mut self, mut userpos: usize, contents: &[C::Item]) where C::Item: Copy {n if contents.len() == 0 { return; }n n userpos = min(userpos, self.get_userlen());n let (mut cursor, offset) = self.iter_at_userpos(userpos);nn unsafe {n if offset == 0 {n self.insert_at_iter(&mut cursor, &mut conten'n ''''''print(';''''''')'(')''''i'r'p'.'f'l'e's' 'ts.iter().copied(), &mut Self::no_notify);nn self.dbg'n 'self.print();' '_check_cursor_at(&cursor, userpos, contents.len());n } else {n let current_item = cursor.current_item();n let (start, end) = C::split_item(current_item, offset);n // Move the cursor back to the start of the item we'ren // splitting.n cursor.move_to_item_start(self.head.height, offset);n 'n 'self.print();' ' // This feels pretty inefficient; but its probably fine.n self.replace_at_iter(&mut cursor, 1, &mut iter::once(start), &mut Self::no_notify);n self.insert_at_iter(&mut cursor, &mut contents.iter().copied(), &mut Self::no_notify);nn // There's no clean way to keep the cursor steady for the finaln // insert. We'll just make sure the cursor is in the rightn // position before that call for now.n self.dbg_check_cursor_at(&cursor, userpos, contents.len());nn self.insert_at_iter(&mut cursor, &mut iter::once(end), &mut Self::no_notify);n }n }nn }nn pub fn del_at(&mut self, mut userpos: usize, num_items: usize) {n userpos = min(userpos, self.get_userlen());n // We can't easily trim num_items.n // num_items = min(length, self.num_chars() - pos);n if num_items == 0 { return; }nn let (mut cursor, offset) = self.iter_at_userpos(userpos);n assert_eq!(offset, 0, 'Splitting nodes not yet supported');nn unsafe { self.del_at_iter(&mut cursor, num_items); }nn if cfg!(debug_assertions) {n let (c2, _) = self.iter_at_userpos(userpos);n if &cursor != &c2 { panic!('Invalid cursor after delete'); }n }n }n}nnnimpl<C: ListConfig> SkipList<C> where C::Item: PartialEq {n pub fn eq_list(&self, other: &[C::Item]) -> bool {n let mut pos = 0;n let other_len = other.len();nn for node in self.iter() {n let my_data = node.content_slice();n let my_len = my_data.len();nn if pos + my_len > other_len || my_data != &other[pos..pos + my_data.len()] {n return falsen }n pos += my_data.len();n }nn return pos == other_len;n }n}nnimpl<C: ListConfig> Drop for SkipList<C> {n fn drop(&mut self) {n let mut node = self.head.first_skip_entry().node;n unsafe {n while !node.is_null() {n let next = (*node).first_skip_entry().node;n Node::free(node);n node = next;n }n }n }n}nnnimpl<C: ListConfig> From<&[C::Item]> for SkipList<C> where C::Item: Copy {n fn from(s: &[C::Item]) -> SkipList<C> {n SkipList::new_from_slice(s)n }n}nn// TODO: Remove Item: Copy constraint here.nimpl<C: ListConfig> From<Vec<C::Item>> for SkipList<C> where C::Item: Copy {n fn from(s: Vec<C::Item>) -> SkipList<C> {n SkipList::new_from_slice(s.as_slice())n }n}nnimpl<C: ListConfig> Into<Vec<C::Item>> for &SkipList<C> where C::Item: Copy {n fn into(self) -> Vec<C::Item> {n let mut content: Vec<C::Item> = Vec::with_capacity(self.num_items);n''use std::alloc::{alloc, dealloc, Layout};nuse std::cmp::min;nuse std::marker::PhantomData;nnuse std::fmt;nnuse rand::{RngCore, Rng, SeedableRng};nuse rand::rngs::SmallRng;nn/// The likelyhood a node will have height (n+1) instead of nnconst BIAS: u8 = 100; // out of 256.nn/// The number of items in each node. Must fit in a u8 thanks to Node.n#[cfg(debug_assertions)]nconst NODE_NUM_ITEMS: usize = 10;nn#[cfg(not(debug_assertions))]nconst NODE_NUM_ITEMS: usize = 100;nn/// Rope operations will move to linear time after NODE_STR_SIZE * 2 ^n/// MAX_HEIGHT length. (With a smaller constant the higher this is). On the flipn/// side, cursors grow linearly with this number; so smaller is marginallyn/// better when the contents are smaller.n#[cfg(debug_assertions)]nconst MAX_HEIGHT: usize = 5;nn#[cfg(not(debug_assertions))]nconst MAX_HEIGHT: usize = 10;nnnconst MAX_HEIGHT_U8: u8 = MAX_HEIGHT as u8; // convenience.nnpub struct ItemMarker<'a, C: ListConfig> {n ptr: *mut Node<C>,n _phantom: PhantomData<&'a SkipList<C>>n}nn/// The whole list is configured through a single generic trait parameternpub trait ListConfig {n type Item: Default + Copy; //+ std::fmt::Debug;nn /// Applications which have custom sizes (or do their ownn /// run-length-encoding) can define their own size function for items. Whenn /// items are inserted or replaced, the position is specified using then /// custom size defined here.n fn get_usersize(_item: &Self::Item) -> usize { 1 }nn fn userlen_of_slice(items: &[Self::Item]) -> usize {n items.iter().fold(0, |acc, item| {n acc + Self::get_usersize(item)n })n }nn fn split_item(_item: &Self::Item, _at: usize) -> (Self::Item, Self::Item) {n unimplemented!('Cannot insert in the middle of an item - split_item is not defined in trait');n }nn // fn notify(&mut self, _items: &[Self::Item], _at_marker: ItemMarker<Self>) where Self: Sized {n // }n n}nnpub trait Queryable {n type Query;nn // Returns Some(offset) into the item if its contained. Otherwise None.n fn contains_item(&self, query: &Self::Query) -> Option<usize>;n}nn/// This represents a single entry in either the nexts pointers list or in ann/// iterator.n#[derive(Debug, PartialEq, Eq)]nstruct SkipEntry<C: ListConfig> {n /// The node being pointed to.n node: *mut Node<C>,nn /// The number of *items* between the start of the current node and then /// start of the next node. That means nexts entry 0 contains the length ofn /// the current node.n skip_usersize: usize,n}nn// We can't use #[derive()] here for Copy and Clone due to a bug in the rustn// compiler: https://github.com/rust-lang/rust/issues/26925nimpl<C: ListConfig> Copy for SkipEntry<C> {}nimpl<C: ListConfig> Clone for SkipEntry<C> {n fn clone(&self) -> Self { *self }n}nnimpl<C: ListConfig> SkipEntry<C> {n fn new_null() -> Self {n SkipEntry { node: ptr::null_mut(), skip_usersize: 0 }n }n}nnnn/// The node structure is designed in a very fancy way which would be more atn/// home in C or something like that. The basic idea is that the node structuren/// is fixed size in memory, but the proportion of that space taken up byn/// characters and by the height differ depending on a node's height. Thisn/// results in a lot of `unsafe` blocks. I think the tradeoff is worth it but In/// could be wrong here. You probably wouldn't lose much performance in practicen/// by replacing the inline structure with a smallvec - but that would wasten/// memory in small nodes, and require extra pointer indirection on large nodes.n/// It also wouldn't remove all the unsafe here.n///n/// A different representation (which might be better or worse - I can't tell)n/// would be to have the nodes all be the same size in memory and change then/// *proportion* of the node's memory that is used by the string field vs then/// next pointers. That might be lighter weight for the allocator because then/// struct itself would be a fixed size; but I'm not sure if it would be better.n#[repr(C)] // Prevent parameter reordering.nstruct Node<C: ListConfig> {n /// We start with the items themselves. Only the first `num_items` of thisn /// list is in use. The user specified length of the items in the node isn /// stored in nexts[0].skip_items. This is initialized withn /// Default::default() for the type, but when MaybeUninit completely lands,n /// it will be possible to make this a tiny bit faster by leaving the listn /// initially uninitialized.n items: [C::Item; NODE_NUM_ITEMS],nn /// Number of items in `items` in use / filled.n num_items: u8,nn /// Height of nexts array.n height: u8,nn /// With the heads array as is, we have no way to go from a marker back to an /// cursor (which is required to insert at that location in the list). Forn /// that we need to be able to figure out at each level of the nextsn /// pointers which object points to us, and the offset from that element ton /// the current element. Anyway, for markers to work we need this.n parent: *mut Node<C>,nn // #[repr(align(std::align_of::<SkipEntry>()))]n n /// In reality this array has the size of height, allocated using more orn /// less direct calls to malloc() at runtime based on the randomly generatedn /// size. The size is always at least 1.n nexts: [SkipEntry<C>; 0],n}nn// Make sure nexts uses correct alignment. This should be guaranteed by repr(C)n// This test will fail if this ever stops being true.n#[test]nfn test_align() {n struct TestConfig;n impl ListConfig for TestConfig {n type Item = u8;n fn get_usersize(_item: &Self::Item) -> usize { 1 }n }n #[repr(C)] struct Check([SkipEntry<TestConfig>; 0]);n assert!(mem::align_of::<Check>() >= mem::align_of::<SkipEntry<TestConfig>>());n // TODO: It'd be good to also check the alignment of the nexts field in Node.n}nnfn random_height<R: RngCore>(rng: &mut R) -> u8 {n let mut h: u8 = 1;n // Should I use a csrng here? Does it matter?n while h < MAX_HEIGHT_U8 && rng.gen::<u8>() < BIAS { h+=1; }n hn}nn#[repr(C)]npub struct SkipList<C: ListConfig> {n // TODO: Consider putting the head item on the heap. For the use case heren // its almost certainly fine either way. The code feels a bit cleaner if itsn // on the heap (and then iterators will be able to outlast a move of then // skiplist parent). But its also very nice having the code run fast forn // small lists. Most lists are small, and it makes sense to optimize forn // that.nn // TODO: For safety, pointers in to this structure should be Pin<> if wen // ever want to hold on to iterators.nn /// The total number of items in the skip list. This is not used internally -n /// just here for bookkeeping.n num_items: usize,n /// Size of the list in user specified units.n num_usercount: usize,nn /// The RNG we use to generate node heights. Specifying it explicitly allowsn /// unit tests and randomizer runs to be predictable, which is very helpfuln /// during debugging. I'm still not sure how the type of this should ben /// specified. Should it be a generic parameter? Box<dyn *>?n /// ??n rng: Option<SmallRng>,nn /// The first node is inline. The height is 1 more than the max height we'ven /// ever used. The highest next entry points to {null, total usersize}.n head: Node<C>,nn /// This is so dirty. The first node is embedded in SkipList; but we need ton /// allocate enough room for height to get arbitrarily large. I could insistn /// on SkipList always getting allocated on the heap, but for small lists itsn /// much better to be on the stack.n ///n /// So this struct is repr(C) and I'm just padding out the struct directly.n /// All accesses should go through head because otherwise I think we violaten /// aliasing rules.n _nexts_padding: [SkipEntry<C>; MAX_HEIGHT],n}nnnnimpl<C: ListConfig> Node<C> {n // Do I need to be explicit about the lifetime of the references being tiedn // to the lifetime of the node?n fn nexts(&self) -> &[SkipEntry<C>] {n unsafe {n std::slice::from_raw_parts(self.nexts.as_ptr(), self.height as usize)n }n }nn fn nexts_mut(&mut self) -> &mut [SkipEntry<C>] {n unsafe {n std::slice::from_raw_parts_mut(self.nexts.as_mut_ptr(), self.height as usize)n }n }nn fn layout_with_height(height: u8) -> Layout {n Layout::from_size_align(n mem::size_of::<Node<C>>() + mem::size_of::<SkipEntry<C>>() * (height as usize),n mem::align_of::<Node<C>>()).unwrap()n }nn fn alloc_with_height(height: u8) -> *mut Node<C> {n assert!(height >= 1 && height <= MAX_HEIGHT_U8);nn unsafe {n let node = alloc(Self::layout_with_height(height)) as *mut Node<C>;n (*node) = Node {n items: [C::Item::default(); NODE_NUM_ITEMS],n num_items: 0,n height: height,n parent: ptr::null_mut(),n nexts: [],n };nn for next in (*node).nexts_mut() {n *next = SkipEntry::new_null();n }nn noden }n }nn fn alloc<R: RngCore>(rng: &mut R) -> *mut Node<C> {n Self::alloc_with_height(random_height(rng))n }nn unsafe fn free(p: *mut Node<C>) {n dealloc(p as *mut u8, Self::layout_with_height((*p).height));n }nn fn content_slice(&self) -> &[C::Item] {n &self.items[..self.num_items as usize]n }nn // The height is at least 1, so this is always valid.n fn first_skip_entry<'a>(&self) -> &'a SkipEntry<C> {n unsafe { &*self.nexts.as_ptr() }n }nn fn first_skip_entry_mut<'a>(&mut self) -> &'a mut SkipEntry<C> {n unsafe { &mut *self.nexts.as_mut_ptr() }n }nn // TODO: Rename to len() ?n fn get_userlen(&self) -> usize {n self.first_skip_entry().skip_usersizen }n n fn get_next_ptr(&self) -> *mut Node<C> {n self.first_skip_entry().noden }n}nnstruct NodeIter<'a, C: ListConfig>(Option<&'a Node<C>>);nimpl<'a, C: ListConfig> Iterator for NodeIter<'a, C> {n type Item = &'a Node<C>;nn fn next(&mut self) -> Option<&'a Node<C>> {n let prev = self.0;n if let Some(n) = self.0 {n *self = NodeIter(unsafe { n.first_skip_entry().node.as_ref() });n }n prevn }n}nn/// This is a set of pointers with metadata into a location in the list neededn/// to skip ahead, delete and insert in items. A cursor is reasonably heavyn/// weight - we fill in and maintain as many entries as the height of the listn/// dictates.n///n/// This is not needed for simply iterating sequentially through nodes and data.n/// For that look at NodeIter.n///n/// Note most/all methods using cursors are unsafe. This is because cursors usen/// raw mutable pointers into the list, so when used the following rules have ton/// be followed:n///n/// - Whenever a write happens (insert/remove/replace), any cursor not passed ton/// the write function is invalid.n/// - While a cursor is held the SkipList struct should be considered pinned andn/// must not be moved or deletedn#[derive(Copy, Clone)]npub struct Cursor<C: ListConfig> {n // TODO: Add a phantom lifetime reference to the skip list root for safety.nnn /// The global user position of the cursor in the entire list. This is usedn /// for when the max seen height increases, so we can populate previouslyn /// unused entries in the cursor and in the head node.n ///n /// This field isn't strictly necessary - earlier versions tacked this on ton /// the last item in entries... I'm still not sure the cleanest way to don /// this.n userpos: usize,nn /// When the userpos of an entry is 0 (totally valid and useful), a cursorn /// becomes ambiguous with regard to where exactly its pointing in then /// current entry. This is used to resolve that ambiguity.n local_index: usize,nn entries: [SkipEntry<C>; MAX_HEIGHT],n}nnimpl<C: ListConfig> Cursor<C> {n fn update_offsets(&mut self, height: usize, by: isize) {n for i in 0..height {n unsafe {n // This is weird but makes sense when you realise the nexts inn // the cursor are pointers into the elements that have then // actual pointers.n // Also adding a usize + isize is awful in rust :/n let skip = &mut (*self.entries[i].node).nexts_mut()[i].skip_usersize;n *skip = skip.wrapping_add(by as usize);n }n }n }nn /// Move a cursor to the start of the next node. Returns the new node (or an /// nullptr if this is the end of the list).n fn advance_node(&mut self) -> *mut Node<C> {n unsafe {n let SkipEntry { node: e, skip_usersize: offset } = self.entries[0];n // offset tells us how far into the current element we are (inn // usersize). We need to increment the offsets by the entry'sn // remaining length to get to the start of the next node.n let advance_by = (*e).get_userlen() - offset;n let next = (*e).get_next_ptr();n let height = (*next).height as usize;nn for i in 0..height {n self.entries[i] = SkipEntry {n node: next,n skip_usersize: 0n };n }nn for i in height..self.entries.len() {n self.entries[i].skip_usersize += advance_by;n }nn self.userpos += advance_by;n self.local_index = 0;nn nextn }n }nn fn is_at_node_end(&self) -> bool {n self.local_index == unsafe { (*self.here_ptr()).num_items } as usizen }nn fn advance_item(&mut self, height: u8) {n if self.is_at_node_end() { self.advance_node(); }n let usersize = C::get_usersize(unsafe { self.current_item() });nn for entry in &mut self.entries[0..height as usize] {n entry.skip_usersize += usersize;n }n self.userpos += usersize;n self.local_index += 1;n }nn fn advance_by_items(&mut self, num: usize, height: u8) {n for _ in 0..num { self.advance_item(height); }n }nn fn move_to_item_start(&mut self, height: u8, offset: usize) {n for entry in &mut self.entries[0..height as usize] {n entry.skip_usersize -= offset;n }n self.userpos -= offset;n }nn unsafe fn current_item(&mut self) -> &C::Item {n &(*self.here_ptr()).items[self.local_index]n }nn /// Get the pointer to the cursor's current noden fn here_ptr(&self) -> *mut Node<C> {n self.entries[0].noden }n}nnimpl<C: ListConfig> PartialEq for Cursor<C> {n /// Warning: This returns false if one cursor is at the end of a node, andn /// the other at the start of the next node. Almost all code in this libraryn /// leaves cursors at the end of nodes, so this shouldn't matter too much inn /// practice.n fn eq(&self, other: &Self) -> bool {n if self.userpos != other.userposn || self.local_index != other.local_index {return false; }nn for i in 0..MAX_HEIGHT {n let a = &self.entries[i];n let b = &other.entries[i];n if a.node != b.node || a.skip_usersize != b.skip_usersize { return false; }n }n truen }n}nimpl<C: ListConfig> Eq for Cursor<C> {}nnimpl<C: ListConfig> fmt::Debug for Cursor<C> {n fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {n f.debug_struct('Cursor')n .field('userpos', &self.userpos)n .field('local_index', &self.local_index)n .finish()n }n}nnimpl<C: ListConfig> SkipList<C> {n pub fn new() -> Self {n SkipList::<C> {n num_items: 0,n num_usercount: 0,n rng: None,n head: Node {n items: [C::Item::default(); NODE_NUM_ITEMS],n num_items: 0,n height: 1, // Stores max height of list nodesn parent: ptr::null_mut(),n nexts: [],n },n _nexts_padding: [SkipEntry::new_null(); MAX_HEIGHT],n }n }nn pub fn init_rng_from_seed(&mut self, seed: u64) {n self.rng = Some(SmallRng::seed_from_u64(seed));n }nn fn get_rng(&mut self) -> &mut SmallRng {n // I'm sure there's a nicer way to implement this.n if self.rng.is_none() {n // We'll use a stable RNG in debug mode so the tests are stable.n if cfg!(debug_assertions) {n self.init_rng_from_seed(123);n } else {n self.rng = Some(SmallRng::from_entropy());n }n }n self.rng.as_mut().unwrap()n }nn pub fn new_from_slice(s: &[C::Item]) -> Self {n let mut rope = Self::new();n rope.insert_at(0, s);n ropen }nn pub fn get_userlen(&self) -> usize {n self.num_usercountn }nn fn iter(&self) -> NodeIter<C> { NodeIter(Some(&self.head)) }n n pub fn len_items(&self) -> usize {n self.num_items as usizen }nn fn heads_mut(&mut self) -> &mut [SkipEntry<C>] {n unsafe {n std::slice::from_raw_parts_mut(self.head.nexts.as_mut_ptr(), self._nexts_padding.len())n }n }nn fn is_head(&self, node: *const Node<C>) -> bool {n node as *const _ == &self.head as *const _n }nn /// Walk the list and validate internal constraints. This is used forn /// testing the structure itself, and should generally not be called byn /// users.n pub fn check(&self) {n // #[cfg(test)]n {n // self.print();n assert!(self.head.height >= 1);n assert!(self.head.height <= MAX_HEIGHT_U8);nn let head_ptr = &self.head as *const _ as *mut _;n // let skip_over = self.get_top_entry();n // println!('Skip over skip chars {}, num bytes {}', skip_over.skip_items, self.num_bytes);nn let mut prev: [*const Node<C>; MAX_HEIGHT] = [ptr::null(); MAX_HEIGHT];nn let mut iter = [SkipEntry {n // Bleh.n node: head_ptr,n // The skips will store the total distance travelled since then // start of this traversal at each height. All the entries aboven // head.height are ignored though.n skip_usersize: 0n }; MAX_HEIGHT];nn let mut num_items = 0;n let mut num_usercount = 0;nn for (_i, n) in self.iter().enumerate() {n // println!('visiting {:?}', n.as_str());n if !self.is_head(n) { assert!(n.num_items > 0); }n assert!(n.height <= MAX_HEIGHT_U8);n assert!(n.num_items as usize <= NODE_NUM_ITEMS);nn // Make sure the number of items matches the countn let local_count = C::userlen_of_slice(&n.items[0..n.num_items as usize]);n assert_eq!(local_count, n.get_userlen());nn let expect_parent = if self.is_head(n) {n ptr::null() // The head's parent is nulln } else if n.height == self.head.height {n &self.head as *const _ // Max height nodes point back to headn } else {n prev[n.height as usize]n };nn // println!('visiting {} {:?}', i, n as *const _);n // dbg!(n as *const _);n // dbg!((n as *const _, (*n).height));n // dbg!(n.parent);n // dbg!(&self.head as *const _);nn assert_eq!(n.parent as *const _, expect_parent, 'invalid parent');n n for (i, entry) in iter[0..n.height as usize].iter_mut().enumerate() {n assert_eq!(entry.node as *const _, n as *const _);n assert_eq!(entry.skip_usersize, num_usercount);nn // println!('replacing entry {:?} with {:?}', entry, n.nexts()[i].node);n prev[i] = n;n entry.node = n.nexts()[i].node;n entry.skip_usersize += n.nexts()[i].skip_usersize;n }nn num_items += n.num_items as usize;n num_usercount += n.get_userlen();nn // Check the value returned by the iterator functions matches.n let (mut normal_iter, local_offset) = self.iter_at_userpos(num_usercount);n assert_eq!(local_offset, 0);nn // Dirty hack. If n has 0-sized elements at the end, the normaln // cursor won't be at the end...n while normal_iter.here_ptr() != n as *const _ as *mut _ {n normal_iter.advance_node();n }n normal_iter.local_index = n.num_items as usize;n let node_iter = unsafe { self.iter_at_node(n, n.get_userlen(), n.num_items as usize) };n assert_eq!(normal_iter, node_iter);n }nn for entry in iter[0..self.head.height as usize].iter() {n // println!('{:?}', entry);n assert!(entry.node.is_null());n assert_eq!(entry.skip_usersize, num_usercount);n }n n // println!('self bytes: {}, count bytes {}', self.num_bytes, num_bytes);n assert_eq!(self.num_items, num_items);n assert_eq!(self.get_userlen(), num_usercount);n }n }n n n /// Internal function for creating a cursor at a particular location in then /// skiplist. The returned cursor contains list of nodes which point pastn /// the specified position, as well as offsets of how far into theirn /// character lists the specified characters are.n ///n /// Sometimes a call to iter_at_userpos is ambiguous:n ///n /// - The item can contain items with zero usersize. The cursor could pointn /// to any of them.n /// - If the location is at the end of a node, it is equally valid to returnn /// a position at the start of the next node.n ///n /// Because its impossible to move backwards in the list, iter_at_userposn /// returns the first admissible location with the specified userpos.n /// n /// Returns (cursor, offset into the specified item).n ///n /// TODO: This should be Pin<&self>.n fn iter_at_userpos(&self, target_userpos: usize) -> (Cursor<C>, usize) {n assert!(target_userpos <= self.get_userlen());nn let mut e: *const Node<C> = &self.head;n let mut height = self.head.height as usize - 1;n n let mut offset = target_userpos; // How many more items to skipnn // We're populating the head node pointer to simplify the case when then // iterator grows. We could put offset into the skip_usersize but itn // would only be *mostly* correct, not always correct. (Since cursorn // entries above height are not updated by insert.)n let mut cursor = Cursor {n entries: [SkipEntry {n node: &self.head as *const _ as *mut _,n skip_usersize: usize::MAXn }; MAX_HEIGHT],n local_index: 0,n userpos: target_userpos,n };nn loop { // while height >= 0n let en = unsafe { &*e };n let next = en.nexts()[height];n let skip = next.skip_usersize;n if offset > skip {n // Go right.n debug_assert!(e == &self.head || en.num_items > 0);n offset -= skip;n e = next.node;n assert!(!e.is_null(), 'Internal constraint violation: Reached rope end prematurely');n } else {n // Record this and go down.n cursor.entries[height] = SkipEntry {n skip_usersize: offset,n node: e as *mut Node<C>, // This is pretty grossn };nn if height == 0 { break; } else { height -= 1; }n }n };nn // We should always land within the node we're pointing to.n debug_assert!(offset <= unsafe { &*cursor.here_ptr() }.get_userlen());nn // We've found the node. Now look for the index within the node.n let en = unsafe { &*e };n let mut index = 0;nn while offset > 0 {n assert!(index < en.num_items as usize);n n let usersize = C::get_usersize(&en.items[index]);n if usersize > offset { break; } // We're in the middle of an item.n offset -= usersize;n index += 1;n }n cursor.local_index = index;nn (cursor, offset)n }nn unsafe fn iter_at_node(&self, n: *const Node<C>, mut offset: usize, local_index: usize) -> Cursor<C> {n let mut n = n as *mut Node<C>; // We don't mutate, but we need a mut ptr.nn let mut cursor = Cursor {n userpos: 0, // We'll set this later.n local_index: local_index,n entries: [SkipEntry {n node: &self.head as *const _ as *mut _,n skip_usersize: usize::MAXn }; MAX_HEIGHT],n };nn let mut h = 0;n loop {n while h < (*n).height as usize {n cursor.entries[h] = SkipEntry {n node: n,n skip_usersize: offsetn };nn h += 1;n }nn let parent = (*n).parent;n // Reached the head.n if parent.is_null() { break; }nn // If we're the same height as the parent its fine.n debug_assert!((*parent).height as usize > hn || (self.is_head(parent) && (*parent).height as usize == h));nn // Walk from parent back to n, figuring out the offset.n let mut c = parent;n // let walk_height = (*parent).height as usize - 2;n let walk_height = (*n).height as usize - 1;n while c != n {n let elem = (*c).nexts()[walk_height];n offset += elem.skip_usersize;n c = elem.node;n }nn n = parent;n }nn cursor.userpos = offset;n cursorn }nn pub fn iter_at_marker(&mut self, marker: ItemMarker<C>, query: &<C::Item as Queryable>::Query) -> Cursor<C> where C::Item: Queryable {n // The marker gives us a pointer into a node. Find the item.n unsafe {n let n = marker.ptr;nn let mut offset: usize = 0;n let mut local_index = None;n for (i, item) in (*n).content_slice().iter().enumerate() {n if let Some(item_offset) = item.contains_item(query) {n offset += item_offset;n local_index = Some(i);n break;n } else {n offset += C::get_usersize(item);n }n }nn let local_index = local_index.expect('Invalid marker - item not found in node');n self.iter_at_node(n, offset, local_index)n }n }nn // Internal fn to create a new node at the specified iterator filled withn // the specified content. The passed cursor should point at the end of then // previous node. It will be updated to point to the end of the newlyn // inserted content.n // unsafe fn insert_node_at(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item], new_userlen: usize, move_cursor: bool) {n unsafe fn insert_node_at<Notify>(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item], new_userlen: usize, move_cursor: bool, notify: &mut Notify)n where Notify: FnMut(&[C::Item], ItemMarker<C>) {nn // println!('Insert_node_at {} len {}', contents.len(), self.num_bytes);n debug_assert_eq!(new_userlen, C::userlen_of_slice(contents));n assert!(contents.len() <= NODE_NUM_ITEMS);nn let new_node_ptr = Node::alloc(self.get_rng());n let new_node = &mut *new_node_ptr;n new_node.num_items = contents.len() as u8;n new_node.items[..contents.len()].copy_from_slice(contents);nn let new_height = new_node.height;n let new_height_usize = new_height as usize;nn let mut head_height = self.head.height as usize;n while head_height < new_height_usize {n // This seems weird given we're about to overwrite these valuesn // below. What we're doing is retroactively setting up the cursorn // and head pointers *as if* the height had been this high alln // along. This way we only have to populate the higher head valuesn // lazily.n let total_userlen = self.num_usercount;n let nexts = self.heads_mut();n nexts[head_height].skip_usersize = total_userlen;n cursor.entries[head_height].skip_usersize = cursor.userpos;nn head_height += 1; // This is ugly.n self.head.height += 1;n }nn new_node.parent = if new_height_usize == MAX_HEIGHT {n &self.head as *const _ as *mut _n } else { cursor.entries[new_height_usize].node };nn for i in 0..new_height_usize {n let prev_skip = &mut (*cursor.entries[i].node).nexts_mut()[i];n let new_nexts = new_node.nexts_mut();nn // The new node points to the successor (or null)n new_nexts[i] = SkipEntry {n node: prev_skip.node,n skip_usersize: new_userlen + prev_skip.skip_usersize - cursor.entries[i].skip_usersizen };nn // The previous node points to the new noden *prev_skip = SkipEntry {n node: new_node_ptr,n skip_usersize: cursor.entries[i].skip_usersizen };nn // Move the iterator to the end of the newly inserted node.n if move_cursor {n cursor.entries[i] = SkipEntry {n node: new_node_ptr,n skip_usersize: new_userlenn };n }n }nn for i in new_height_usize..head_height {n (*cursor.entries[i].node).nexts_mut()[i].skip_usersize += new_userlen;n if move_cursor {n cursor.entries[i].skip_usersize += new_userlen;n }n }nn // Update parents.n if new_height_usize > 1 {nn let mut n = new_node_ptr;n let mut skip_height = 0;nn loop {n n = (*n).nexts_mut()[skip_height].node;n if n.is_null() || (*n).height >= new_height { break; }n n (*n).parent = new_node_ptr;n skip_height = usize::max(skip_height, (*n).height as usize - 1);n }n }n n self.num_items += contents.len();n self.num_usercount += new_userlen;n if move_cursor {n cursor.userpos += new_userlen;n cursor.local_index = contents.len();n }nn notify(contents, ItemMarker {n ptr: new_node_ptr,n _phantom: PhantomDatan });n }nn // unsafe fn insert_at_iter(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item]) {n unsafe fn insert_at_iter<Notify>(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item], notify: &mut Notify)n where Notify: FnMut(&[C::Item], ItemMarker<C>) {n // iter specifies where to insert.nn let mut e = cursor.here_ptr();nn // The insertion offset into the destination node.n assert!(cursor.userpos <= self.num_usercount);n assert!(cursor.local_index <= (*e).num_items as usize);nn // We might be able to insert the new data into the current node, depending onn // how big it is.n let num_inserted_items = contents.len();n let num_inserted_usercount = C::userlen_of_slice(contents);nn // Can we insert into the current node?n let mut insert_here = (*e).num_items as usize + num_inserted_items <= NODE_NUM_ITEMS;nn // Can we insert into the start of the successor node?n if !insert_here && cursor.local_index == (*e).num_items as usize && num_inserted_items <= NODE_NUM_ITEMS {n // We can insert into the subsequent node if:n // - We can't insert into the current noden // - There _is_ a next node to insert inton // - The insert would be at the start of the next noden // - There's room in the next noden if let Some(next) = (*e).first_skip_entry_mut().node.as_mut() {n if next.num_items as usize + num_inserted_items <= NODE_NUM_ITEMS {n cursor.advance_node();n e = next;nn insert_here = true;n }n }n }nn let item_idx = cursor.local_index;n let e_num_items = (*e).num_items as usize; // convenience.nn if insert_here {n // println!('insert_here {}', contents);n // First push the current items later in the arrayn let c = &mut (*e).items;n if item_idx < e_num_items {n c[..].copy_within(item_idx..e_num_items,n item_idx + num_inserted_items);n }nn // Then copy in the new itemsn c[item_idx..item_idx + num_inserted_items].copy_from_slice(contents);nn (*e).num_items += num_inserted_items as u8;n self.num_items += num_inserted_items;n self.num_usercount += num_inserted_usercount;nn // .... aaaand update all the offset amounts.n cursor.update_offsets(self.head.height as usize, num_inserted_usercount as isize);nn // Usually the cursor will be discarded after one change, but forn // consistency of compound edits we'll update the cursor to point ton // the end of the new content.n for entry in cursor.entries[0..self.head.height as usize].iter_mut() {n entry.skip_usersize += num_inserted_usercount;n }n cursor.userpos += num_inserted_usercount;n cursor.local_index += num_inserted_items;nn notify(contents, ItemMarker {n ptr: e,n _phantom: PhantomDatan });n } else {n // There isn't room. We'll need to add at least one new node to then // list. We could be a bit more careful here and copy as much asn // possible into the current node - that would decrease the numbern // of new nodes in some cases, but I don't think the performancen // difference will be large enough to justify the complexity.nn // If we're not at the end of the current node, we'll need to removen // the end of the current node's data and reinsert it later.n let num_end_items = e_num_items - item_idx;nn let (end_items, end_usercount) = if num_end_items > 0 {n // We'll mark the items as deleted from the node, while leavingn // the data itself there for now to avoid a copy.nn // Note that if we wanted to, it would also be correct (andn // slightly more space efficient) to pack some of the newn // string's characters into this node after trimming it.n let end_items = &(*e).items[item_idx..e_num_items];n (*e).num_items = item_idx as u8;n let end_usercount = (*e).get_userlen() - cursor.entries[0].skip_usersize;nn cursor.update_offsets(self.head.height as usize, -(end_usercount as isize));nn // We need to trim the size off because we'll add the charactersn // back with insert_node_at.n self.num_usercount -= end_usercount;n self.num_items -= num_end_items;nn (Some(end_items), end_usercount)n } else {n (None, 0)n };nn // Now we insert new nodes containing the new character data. Then // data is broken into pieces with a maximum size of NODE_NUM_ITEMS.n // As further optimization, we could try and fit the last piece inton // the start of the subsequent node. That optimization hasn't beenn // added.n n for chunk in contents.chunks(NODE_NUM_ITEMS) {n let userlen = C::userlen_of_slice(chunk);n self.insert_node_at(cursor, chunk, userlen, true, notify);n }nn // TODO: Consider recursively calling insert_at_iter() here insteadn // of making a whole new node for the remaining content.n if let Some(end_items) = end_items {n // Passing false to indicate we don't want the cursor updatedn // after this - it should remain at the end of the newlyn // inserted content, which is *before* this end bit.n self.insert_node_at(cursor, end_items, end_usercount, false, notify);n }n }n }nn // unsafe fn insert_at_iter(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item]) {n // self.insert_at_iter_and_notify(cursor, contents, Self::no_notify);n // }nn /// Interestingly unlike the original, here we only care about specifyingn /// the number of removed items by counting them. We do not use usersize inn /// the deleted item count.n ///n /// If the deleted content occurs at the start of a node, the cursor passedn /// here must point to the end of the previous node, not the start of then /// current node.n unsafe fn del_at_iter(&mut self, cursor: &mut Cursor<C>, mut num_deleted_items: usize) {n if num_deleted_items == 0 { return; }nn let mut item_idx = cursor.local_index;n let mut e = cursor.here_ptr();n while num_deleted_items > 0 {n // self.print();n // if cfg!(debug_assertions) { self.check(); }n if item_idx == (*e).num_items as usize {n let entry = (*e).first_skip_entry();n // End of current node. Skip to the start of the next one. We'ren // intentionally not updating the iterator because if we deleten // a whole node we need the iterator to point to the previousn // element. And if we only delete here, the iterator doesn'tn // need to be moved.n e = entry.node;n if e.is_null() { panic!('Cannot delete past the end of the list'); }n item_idx = 0;n }nn let e_num_items = (*e).num_items as usize;n let removed_here = min(num_deleted_items, e_num_items - item_idx);n n let height = (*e).height as usize;n let removed_userlen;nn if removed_here < e_num_items || e as *const _ == &self.head as *const _ {n // Just trim the node down.n let trailing_items = e_num_items - item_idx - removed_here;n n let c = &mut (*e).items;n removed_userlen = C::userlen_of_slice(&c[item_idx..item_idx + removed_here]);n if trailing_items > 0 {n c[..].copy_within(item_idx + removed_here..e_num_items, item_idx);n }nn (*e).num_items -= removed_here as u8;n self.num_items -= removed_here;n self.num_usercount -= removed_userlen;nn for s in (*e).nexts_mut() {n s.skip_usersize -= removed_userlen;n }n } else {n // Remove the node from the skip list entirely. e should be then // next node after the position of the iterator.n assert_ne!(cursor.here_ptr(), e);nn removed_userlen = (*e).get_userlen();n let next = (*e).first_skip_entry().node;nn // println!('removing {:?} contents {:?} height {}', e, (*e).content_slice(), height);nn for i in 0..height {n let s = &mut (*cursor.entries[i].node).nexts_mut()[i];n s.node = (*e).nexts_mut()[i].node;n s.skip_usersize += (*e).nexts()[i].skip_usersize - removed_userlen;n }nn self.num_items -= (*e).num_items as usize;n self.num_usercount -= removed_userlen;nn // Update parents.n if height > 1 {n let mut n = e;n // let new_parent = cursor.entries[height - 1].node;nn // If you imagine this node as a big building, we need ton // update the parent of all the nodes we cast a shadow over.n // So, if our height is 3 and the next nodes have heights 1n // and 2, they both need new parents.n let mut parent_height = 1;n let cursor_node = cursor.here_ptr();n let cursor_node_height = (*cursor_node).height as usize;n let mut new_parent = if height >= cursor_node_height {n cursor.entries[parent_height].noden } else {n cursor_noden };nn loop {n // dbg!(skip_height);n // dbg!((*n).height as usize);nn n = (*n).nexts_mut()[parent_height - 1].node;n if n.is_null() || (*n).height >= height as u8 { break; }n let n_height = (*n).height as usize;nn // dbg!((*n).content_slice());n // dbg!((*n).height);n n assert_eq!((*n).parent, e);n assert!(n_height >= parent_height - 1);nn if n_height > parent_height {n parent_height = n_height;n if n_height >= cursor_node_height {n new_parent = cursor.entries[parent_height].noden }n }n n (*n).parent = new_parent;n }n }nn Node::free(e);n e = next;n }nn for i in height..self.head.height as usize {n let s = &mut (*cursor.entries[i].node).nexts_mut()[i];n s.skip_usersize -= removed_userlen;n }nn num_deleted_items -= removed_here;nn // if cfg!(debug_assertions) { self.check(); }n }n }nn // unsafe fn insert_at_iter<Notify>(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item], mut notify: Notify)n // where Notify: FnMut(&[C::Item], ItemMarker<C>) {nn unsafe fn replace_at_iter<Notify>(&mut self, cursor: &mut Cursor<C>, mut removed_items: usize, mut inserted_content: &[C::Item], mut notify: Notify)n where Notify: FnMut(&[C::Item], ItemMarker<C>) {n if removed_items == 0 && inserted_content.len() == 0 { return; }nn // Replace as many items from removed_items as we can with inserted_content.n let mut replaced_items = min(removed_items, inserted_content.len());n removed_items -= replaced_items;nn while replaced_items > 0 {n let mut e = cursor.here_ptr();n if cursor.local_index == (*e).num_items as usize {n // Move to the next item.n e = cursor.advance_node();n if e.is_null() { panic!('Cannot replace past the end of the list'); }n }nn let index = cursor.local_index;nn let e_num_items = (*e).num_items as usize;n let replaced_items_here = min(replaced_items, e_num_items - index);nn let old_items = &mut (*e).items[index..index + replaced_items_here];n let new_items = &inserted_content[0..replaced_items_here];nn let new_usersize = C::userlen_of_slice(new_items);n let usersize_delta = new_usersize as isize - C::userlen_of_slice(old_items) as isize;nn // Replace the items themselves. Everything else is commentary.n old_items.copy_from_slice(new_items);nn if usersize_delta != 0 {n cursor.update_offsets(self.head.height as usize, usersize_delta)n }n // I hate this.n self.num_usercount = self.num_usercount.wrapping_add(usersize_delta as usize);nn inserted_content = &inserted_content[replaced_items_here..];n replaced_items -= replaced_items_here;n // We'll hop to the next Node at the start of the next loopn // iteration if needed.n cursor.local_index += replaced_items_here;nn for i in 0..self.head.height as usize {n cursor.entries[i].skip_usersize += new_usersize;n }n cursor.userpos += new_usersize;nn notify(new_items, ItemMarker {n ptr: e,n _phantom: PhantomData,n });n }nn // Ok now one of two things must be true. Either we've run out ofn // items to remove, or we've run out of items to insert.n if inserted_content.len() > 0 {n // Insert!n debug_assert!(removed_items == 0);n self.insert_at_iter(cursor, inserted_content, &mut notify);n } else if removed_items > 0 {n self.del_at_iter(cursor, removed_items);n }n }nn fn dbg_check_cursor_at(&self, cursor: &Cursor<C>, userpos: usize, plus_items: usize) {n if cfg!(debug_assertions) {n // let (mut c2, _) = self.iter_at_userpos(userpos);n let (mut c2, _) = self.iter_at_userpos(userpos);n c2.advance_by_items(plus_items, self.head.height);n assert_eq!(cursor, &c2);n }n }nn fn no_notify(_items: &[C::Item], _marker: ItemMarker<C>) {}nn pub fn replace_at(&mut self, mut start_userpos: usize, removed_items: usize, inserted_content: &[C::Item]) {n start_userpos = min(start_userpos, self.get_userlen());nn let (mut cursor, offset) = self.iter_at_userpos(start_userpos);n assert_eq!(offset, 0, 'Splitting nodes not yet supported');nn unsafe { self.replace_at_iter(&mut cursor, removed_items, inserted_content, Self::no_notify); }nn if cfg!(debug_assertions) {n let (mut c2, _) = self.iter_at_userpos(start_userpos);n c2.advance_by_items(inserted_content.len(), self.head.height);n if &cursor != &c2 { panic!('Invalid cursor after replace'); }n }n }nn pub fn insert_at(&mut self, mut userpos: usize, contents: &[C::Item]) {n if contents.len() == 0 { return; }n n userpos = min(userpos, self.get_userlen());n let (mut cursor, offset) = self.iter_at_userpos(userpos);nn unsafe {n if offset == 0 {n self.insert_at_iter(&mut cursor, contents, &mut Self::no_notify);nn self.dbg_check_cursor_at(&cursor, userpos, contents.len());n } else {n let current_item = cursor.current_item();n let (start, end) = C::split_item(current_item, offset);n // Move the cursor back to the start of the item we'ren // splitting.n cursor.move_to_item_start(self.head.height, offset);n // This feels pretty inefficient; but its probably fine.n self.replace_at_iter(&mut cursor, 1, &[start], &mut Self::no_notify);n self.insert_at_iter(&mut cursor, contents, &mut Self::no_notify);nn // There's no clean way to keep the cursor steady for the finaln // insert. We'll just make sure the cursor is in the rightn // position before that call for now.n self.dbg_check_cursor_at(&cursor, userpos, contents.len());nn self.insert_at_iter(&mut cursor, &[end], &mut Self::no_notify);n }n }nn }nn pub fn del_at(&mut self, mut userpos: usize, num_items: usize) {n userpos = min(userpos, self.get_userlen());n // We can't easily trim num_items.n // num_items = min(length, self.num_chars() - pos);n if num_items == 0 { return; }nn let (mut cursor, offset) = self.iter_at_userpos(userpos);n assert_eq!(offset, 0, 'Splitting nodes not yet supported');nn unsafe { self.del_at_iter(&mut cursor, num_items); }nn if cfg!(debug_assertions) {n let (c2, _) = self.iter_at_userpos(userpos);n if &cursor != &c2 { panic!('Invalid cursor after delete'); }n }n }n}nnnimpl<C: ListConfig> SkipList<C> where C::Item: PartialEq {n pub fn eq_list(&self, other: &[C::Item]) -> bool {n let mut pos = 0;n let other_len = other.len();nn for node in self.iter() {n let my_data = node.content_slice();n let my_len = my_data.len();nn if pos + my_len > other_len || my_data != &other[pos..pos + my_data.len()] {n return falsen }n pos += my_data.len();n }nn return pos == other_len;n }n}nnimpl<C: ListConfig> Drop for SkipList<C> {n fn drop(&mut self) {n let mut node = self.head.first_skip_entry().node;n unsafe {n while !node.is_null() {n let next = (*node).first_skip_entry().node;n Node::free(node);n node = next;n }n }n }n}nnnimpl<C: ListConfig> From<&[C::Item]> for SkipList<C> {n fn from(s: &[C::Item]) -> SkipList<C> {n SkipList::new_from_slice(s)n }n}nnimpl<C: ListConfig> From<Vec<C::Item>> for SkipList<C> {n fn from(s: Vec<C::Item>) -> SkipList<C> {n SkipList::new_from_slice(s.as_slice())n }n}nnimpl<C: ListConfig> Into<Vec<C::Item>> for &SkipList<C> {n fn into(self) -> Vec<C::Item> {n let mut content = Vec::with_capacity(self.num_items);n''''''''''''''''MaybeUninit;''''''t''''t'a'm''''MaybeUnini';'t''''y'a'M':':'m'e'm':':'d't's' 'e's'u'''''''e's'n'''''''''''''''''NonNul';'l'''''''''''''''''';'r'e't'i':':'d't's' 'e's'u'n''n'o'N':':'r't'p':':'d't's' 'e's'u'n';nuse std::alloc::{alloc, dealloc, Layout};nuse std::cmp::min'''''''''''''''''''PhantomDat';'a'''''n'a'h'P':':'r'e'k'r'a'm':':'d't's' 'e's'u'n'''''''''''''''';'t'm'f':':'d't's' 'e's'u'n'n';nnuse rand::{RngCore, Rng, SeedableRng};nuse rand::rngs::SmallRng;nn/// The likelyhood a node will have height (n+1) instead of nnconst BIAS: u8 = 100; // out of 256.nn/// The number of items in each node. Must ''0'1''''2'''0'2''''0'0'''''''9'9'1'''fit in a u8 thanks to Node.'#[cfg''''''''''''''''s'n'o'i't'r'e's's'a'_'g'u'b'e'd'(test)]'const NODE_NUM_ITEMS: us's'i'n'z'o'e'i' 't'='r'''e'2's'''s'''a'''_' 'g'''u'''b'''e''''0''d'0'1;'n'n''''''''t'o'n'')'(''''''''''o'n')''''!'!'n''#'''!'[cfg(tes''t)]'const NODE_NUM_ITEMS: usize = 1;n'n'''n// const NO'''_'DE_NUM_ITEMS:'' u''size = 100''#[cfg(test)]'n';nconst'5' NODE_''0'1'''NUM_ITEMS: usize ='1''''''0'0'1''''1''''2''''1' 100;nn/// Rope operations will m's'ove'n' to'o' li'i'nea't'r t'r'ime'e' af's'ter's' NO'a'DE_''s'_'STR'n'''// '''g'_S'o'''I'u'Z'i'E 'b'''a, '''''''''''''''d'e'z'i'S' '+' ''t'''''''''''m'''// '''''''d'e'z'i'S' '+''' '*'// ' 2'e'r'' ^n/'e'// MA's'''''''''''''ListConfi'>'g'''''t's'i'L' ':'C''''''''''''pi''''''i'p'n'U''''I''''':':'n'''i'p':':'d't's' '>'''''n'i'p'n'U''Copy''Clone''Copy''''''e'n'o'l'C''C'<';''''/'/''<'''''''''''''''''''':':'d't's'''''':':'t'm'f''''''g'u'b'e'D' '+' ''ItemMarke'''}'{' 'r'''''m'e't'I' 'r'''o'f' 'd'e'z'i'S' 'l'p'm'i'n'X'''''''' 'b'u'''p'''''// '''''// ''''''''' ','a'''''''Li'&'''SkipLis'''>'C'<'t'''''p'i'k'S' 'stConfi'>'g''''''''n'o'C't's''''''n '''''''''''''''''>'a'''<''''PartialEq''''''''l'a'i't'r'a'P' '+' ''''''''''''a't'a'D'm'o't'n'a'h'P' ':'n'o't'n'a'h'''''''''d'e'z'i'S' '+' 'p'_' ','>'C'<'i'L' ':'C'<''''''''''''''''''''''e'd'o'N' 't'u'm'*' ''''' ':'r't'p' '''}''n 'n ' '{' 'r'e'k'r'a'M'm'e't'I' 't'c'u'r't's''''''''' 'f'e'd'e'p'y't'n'n'_'d''s'HEIGH'a'T len'_'g'#[c'g'fg(te'u'st)]''b'''con'e'st '2'NODE_NUM_IT'd'EMS: u''0'n''1''''1''''2'''s''ize = 1;n'''nconst NODE_NUM_ITEMS: usiz''e = 1;''n#[cfg(not(test))]''nconst 'nconst NODE'// ''''// '''_NUM_ITEMS: usize'// ' = 1;'NODE_NUM_ITEMS: usiz'n#[cfg(not(test))]''nconst MAX_HEIGHT: u'// 'size ''= '// '10;'e'''' =' where '''''''''''''''''''''''e'l'b'a'y'r'e'u'Q''''''''''y''n '''// '''''''''''''''n'// ''' ';''''''' ':'y'r'e'u'Q' 'e'p'y't' 'r'e'u'Q'm'e't'I''''''''''''n '''''''''''''''''''''''''''''''''''''''''''''':':'f'l'e'S''''''y'r'e'u'''''''Q''''''''''''''''''''''''''.'e'n'o'N' 'e's'i'w'r''''''f'l'e's''e'h't'O' '.'d'e'n'i'a't'n'o'c' 's't'i' 'f'i' 'm'e't'i' 'e'h't' 'o't'n'i' ')'t'e's'f'f'o'('e'm'o'S''''''''''''''''('e'm'o'C' 's'n'r'u't'e'R''''T' '/'/' '''''n fn contains_item(item: &''Self::Item, query'''''''''''''>'e'z'i's'u'<'n'o'i't'p'O': &'';''''Self::Item) -> bool {n }'''}''n 'n ' '{' 's'n'i'a't'n'o'C' 't'i'a'r't' 'b'u'p'n'n''n ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''n 'unimplemented''''''''''''''''''''''''''''''''' 'r'o'f' 'l'p'm'i' 'm'e't'i'_'s'n'i'a't'n'o'c' 'g'n'i's's'i'm''''''a't'n'o'c''''''''''''''''''''''''''''' 'r'o'f' 'm'e't'i'_'s'n'i'a't'n'o'c' ''''s't'n'e'm'e'l'p'm'I''''';')'('!'''''''l'p'm'i'n'u' n '''''''''''''''}' 'e's'l'a'f' '{' 'l'o'o'b''''B' '>'-' ')'m'e't'I':':'f'l'e'S'&' ':'y'r'e'u'q'''' ','m'e't'I':':'f'l'e'S'&' ':'m'e't'i'*''''&'('m'e't'i'_'s'n'i'a't'n'o'c' 'n'f' 'Self: S'//' '' ' 'iz''ed '' ' 100;''n''n''const MAX_HEIGHT: usi'nconst NODE_NUM_ITEMS: usize = 100;'ze 'n'= 10;n''#[cfg(test)]nco's'n'['st NODE_']'N''t'a'''''''o't'''U''M_ITEMS' where Sel'''''It''Item'''t'I':':'f: Sized''': usize = 1;n#[cfg(not(test))]nconst NODE_NUM_ITEMS: u'_'size = 100;n'th. '_'(With a sm'n '''''''''''''''''''''''''''''''''d'e'z'i'S' ':'f'l'e'S' 'e'r'e'h'w' '''''''''''''''''''''''''''''_'t'a''''ItemMarke'''''f'l'e'S'''''>'C'<'''''' }'n '{' ''''{')'r''''''M'm'e't'I''''''' ':'r'e'k'r'a'm' ','m'e't'I':':'f'l'e'S'&' ':'m'e't'i' ','f'l'e's''''S' 't'u'm'&'('y'f'i't'o'n' 'n'f' '''''''''n '''''n 'n ' 'aller constant the higher this is). On the flipn/// side, cursors grow linearly with this number; so smaller is marginallyn/// better when the contents are sma''0''&'1''''2'''''_'''t'a'''''''''''e'z'i's'u' ':''''''''''''''''''''>'T''''&'''''>'T''''>'T' '''''''''''''f'l'e's'&''''''''''''''''y'p'o'C'''''''''''''''' '''''''')'3'('o'o'F''''''''' '=' '''n ''''''''';')'('h'a'l'b'.'x' ';'x' 't'e'l''''''''''''''''<'t'i'n'>''i'n'U'e'b'y'a'M'''')'3'('o'o'F' '''}''n 'n ' '{' ')'('x' 'n'f'n'n'''g'u'b'e'D' ':'T' 'e'r'e'h'w' '''''' }''n 'n ' '{' ')'('h'a'l'b' 'n'f' ''<'<'T''''''''}''n 'n ' '{' 'o'o'F''<''''''''''' 'l'p'm'i'n'n';'''''''n'n')'('''' 'o'o'F' 't'c'u'r't's'n'n'n''s'o'p' ',''ller.nconst MAX_HEIGHT: us'1'ize = 20;nnconst MAX_HEIGHT_U8: u8 = MAX_HEIGHT as u8; // convenience.nn/// The whole list is configured through a single generic trait parameternpub trait ListConfig {n type Item: Default + Copy;nn /// Applications which have custom sizes (or do their ownn /// run-length-encoding) can define their own size function for items. Whenn /// items are inserted or replaced, the position is specified using then /// custom size defined here.n fn get_usersize(_item: &Self::Item) -> usize { 1 }nn fn userlen_of_slice(items: &[Self::Item]) -> usize {n items.iter().fold(0, |acc, item| {n acc + Self::get_usersize(item)n })n }nn fn split_item(_item: Self::Item) -> (Self::Item, Self::Item) {n unimplemented!('Cannot insert in the middle of an item - split_item is not defined in trait');n }nn // type RngType: rand::RngCore = rand::rngs::SmallRng;n // fn get_rng() -> Self::RngType {n // use rand::SeedableRng;n // // rand::rngs::SmallRng::from_seed(SeedableRng::seed_from_u64(10))n // rand::rngs::SmallRng::from_entropy()n // }n}nn/// This represents a single entry in either the nexts pointers list or in ann/// iterator.n#[derive(Debug, PartialEq, Eq)]nstruct SkipEntry<C: ListConfig> {n /// The node being pointed to.n node: *mut Node<C>,nn /// The number of *items* between the start of the current node and then /// start of the next node. That means nexts entry 0 contains the length ofn /// the current node.n skip_usersize: usize,n}nn// We can't use #[derive()] here for Copy and Clone due to a bug in the rustn// compiler: https://github.com/rust-lang/rust/issues/26925nimpl<C: ListConfig> Copy for SkipEntry<C> {}nimpl<C: ListConfig> Clone for SkipEntry<C> {n fn clone(&self) -> Self { *self }n}nnimpl<C: ListConfig> SkipEntry<C> {n fn new_null() -> Self {n SkipEntry { node: ptr::null_mut(), skip_usersize: 0 }n }n}nnn/// The node structure is designed in a very fancy way which would be more atn/// home in C or something like that. The basic idea is that the node structuren/// is fixed size in memory, but the proportion of that space taken up byn/// characters and by the height differ depending on' '/'// With the heads array as is, we have no way to go from a marker back to' /// cursor (which is required to insert at that location in the list). Forn /// that we need to be able to figure out at each level of the nexts' /// pointers which object points to us, and the offset from that element ton /// the current element'''''''''''''''''''''''''''''''''''''''''''n ''''''''''''''''''''','''>'C'<'';'''' 'e'd'o'N' 't'u'm'*' ':'t'n'e'r'a'p''' ''/''/''/ '.'s'i'h't' 'd'e'e'n' 'e'w' 'k'r'o'w' 'o't' 's'r'e'k'r'a'm' ''''m'r'o'f'''''''e'e'n' 'e'w' ','y'a'w'y'n'A' '.'n /// pointers which object points to us, and''''''''''''''''''''''''''''''''''''''''''''''''''''.'t'n'e'm'e'l'e' 't'n'e'r'r'u'c' 'e'h't' 'o't' 't'n'e'm'e'l'e' 't'a'h't' 'm'o'r'f' 't'e's'f'f'o' 'e'h't' how far into the' an '/' // cursor (which is required t'n'''o'''''''''''''''''''''''''''''''''MaybeUnini''''''''''''''''''''''''''''''''.''''''' 'e'f'a's'n'u''t'e'y' 'd'e'z'i'd'r'''''''''>'T'<''''''MaybeUnini''' ''>'T'<'t''''''e'b'y'a'M''''''i'l'd'r'a'd'n'a't's' 't'o'n' 't's'u'j' 's't'I' '.'t'''''''u'e'b' ''y'a'm':':'m'e'm':':'e'r'o'c'''''':':'d't's'''''''t's' 'm'o'r'f' 'n''''''' 'd'e'l'o't'S' '/'/'n'''' '''''''''''''''''''''''''''''' ''n ' pub unsafe fn slice_get_ref(slice: &[Self]) -> &[T] ' '{n // SAFETY: casting slice to a `*const [T]` is s'MaybeUnini'''>'T'<'t''''''e'b'y'a'M'''afe sin' 'ce the caller guarantees thatn // `slice` is initiali''zed, and`MaybeUninit` is guaranteed to have the same layout as `T`.n // The pointer obtained is valid since it refers to memory owned by `slice` which is an // reference and thus guaranteed to be valid for reads.n unsafe { &*(slice as *const [Self] as *const [T]) }n }' 'n ' '('f'e'r'_'t'e'g'_'e'c'i'l's'_'t'i'n'i''''m'e'b'y'a'm''''''''_'t'i'n'i'n'u'''''''_'e'c'i'l's' 'n'f'n'n' insert at that location in the list)''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''e'h't' 'o't'n'i' 'r'a'f' 'w'o'h' 'd'n'a' ','s'u' 'o't' 's't'n'i'o'p' 't'c'e'j'b'o''''''''s't'c'e'j'b'o' 'h'c'i'h'w' 's'r'e't'n'i'o'p' 's't'x'e'n' 'e'h't' 'f'o' 'l'e'v'e'l' 'h'c'a'e' 't'a' 't'u'o' 'e'r'u'g'i'f' 'o't' 'e'l'b'a' 'e'b' 'o't''''' 'd'e'e'n' 'e'w' 't'a'h't' 'r'o'F' '.' a node'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.')'t's'i'l' 'e'h't' 'n'i' 'n''''''''''n'i' 'o'i't'a'c'o'l' 't'a'h't' 't'a' 't'r'e's'n'i' 'o't' 'd'e'r'i'u'q'e'r' 's'i' 'h'c'i'h'w'(' 'r'o's'r'u'c' 'a' 'o'''''''a' 't' 'k'c'a'b' 'r'e'k'r'a'm' 'a' 'm'o'r'f' 'o'g'''''''''''''''' 'm'o'r'f' 'o't' 'y'a'w''''i' 'o'n' 'e'v'a'h' 'e'w' ','s'i' 's'a' ''''''' 's'y'a'r'r'a' 's'd'a'e'h' 'e'h't' '''''''''''''e'h' 't'h't'i'W'''''''''' ','e'n'o'l'A''W''s height. Thi'uninit_items_arra'')'('y's'MaybeUnini'''''''''')'('n ''''''''' '{' 'e'f'a's'n'u''maybeinit_s''}' 'lice_get_ref'''''e'''''c'i'l's''// '(slice: &[MaybeUninit<T>])''''y'a'm' ''t'i'n'i''''i'n'u':':'t''''''e'b'y'a'M'''n/// '''n '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '+' 'e'd'o'n'(' 'r'e'k'r'a'm' 'a' 'm'o'r'f' 'o'g' 'o't' 'y'a'w' 'o'n' 'e'v'a'h' 'e'w' ','e's'l'e' 'g'n'i'h't'y'r'e'v'e''''' 'e'h't' 'h't'i'W''''''''''''''''''''''''''''''''''''' 'e'v'l'o's' 'd'l'u'o'c' 'I' 's'''' 'y'a'w' 'f'o' 't'o'l' 'a' 's'''e'r'e'h'T' '/'/' 'n ' 'results in a lot of `unsafe` blocks. I think the tradeoff is worth it but In/// could be wrong here. You probably wouldn't lose much performance in practicen/// by replacing the inline s'' '''''''''''''''''''''''''''slice_get_re'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'n'o'i't'a't'n'e'm'e'l'p'm'i' 't'a'h't' 'm'o'r'f' 'n''''''' 'd'e'l'o'''''''l'i't's' 's'i' 'e'd'o'c' 's'i'h'T' '''' '' ''n ' // SAFETY: casting slice to a `*const [T]` is safe since the caller guarantees thatn // `slice` is initialized, and`MaybeUninit` is guaranteed to have the same layout as `T`.n // The pointer'''''''''''''&self.items[..self.num_items as usize';']' '=' 'e'c'i'l's' 't'e'l''n 'MaybeUnini''C::Ite'>'m'<'t''''y'a'M''''Self''C::Item'' 'C::Item'obtained is valid si''n''ce i''t refers to memory owned by `slice''` which is an // reference and thus guaranteed to be valid for reads.n unsafe { &*(slice as *const [Self] as *const [T]) }' 'n ' '.'s'd'n'a'l' ''''''' 's't'i' 'n'e'h'w' 'f':':'t'i'n'i'n'U'e'b'y'a'M'''''''t'i'n'i'n'U' 'e's'U' ':'O'D'O'T' '/'/' '''''''n 'n ' 'tructure with a smallvec - but that would wasten/// memory in small nodes, and require extra pointer indirection on large nodes.n/// It also wouldn't remove all the unsafe here.n///n/// A different representation (which might be better or worse - I can't tell)n/// would be to have the nodes all be the same size in memory and change then/// *proportion* of the node's memory that is used by the string field vs then/// next pointers. That might be lighter weight for the allocator because then/// struct itself would be a fixed size; but I'm not sure if it would be better.n#[repr(C)] // Prevent parameter reordering.nstruct Node<C: ListConfig> {n /// We start with the items themselves. Only the first `num_items` of thisn /// list is in use. The user specified length of the items in the node isn /// stored in nexts[0].skip_items. This is initialized withn /// Default::default() for the type, but when MaybeUninit completely lands,n /// it will be possible to make this a tiny bit faster by leaving the listn /// initially uninitialized.n items: [C::Item; NODE_NUM_ITEMS],nn /// Number of items in `items` in use / filled.n num_items: u8,nn /// Height of nexts array.n height: u8,nn // #[repr(align(std::align_of::<SkipEntry>()))]n n /// In reality this array has the size of height, allocated using more orn /// less direct calls to malloc() at runtime based on the randomly generatedn /// size. The size is always at least 1.n nexts: [SkipEntry<C>; 0],n}nn// Make sure nexts uses correct alignment. This should be guaranteed by repr(C)n// This test will fail if this ever stops being true.n#[test]nfn test_align() {n struct TestConfig;n impl ListConfig for TestConfig {n type Item = u8;n fn get_usersize(_item: &Self::Item) -> usize { 1 }n }n #[repr(C)] struct Check([SkipEntry<TestConfig>; 0]);n assert!(mem::align_of::<Check>() >= mem::align_of::<SkipEntry<TestConfig>>());n // TOD'n 'paren''''''''null_mut(',')'''''l'l'u'n':':'r't'p' ':'t''''''n'e'r'a'p' 'O: It'd be good to also check the alignment of the nexts field in Node.n}nnfn random_height<R: RngCore>(rng: &mut R) -> u8 {n let mut h: u8 = 1;n // Should I use a csrng here? Does it matter?n while h < MAX_HEIGHT_U8 && rng.gen::<u8>() < BIAS { h+=1; }n hn}nn#[repr(C)]npub struct SkipList<C: ListConfig> {n // TODO: Consider putting the head item on the heap. For the use case heren // its almost certainly fine either way. The code feels a bit cleaner if itsn // on the heap (and '''' 'b'u'p'then iterators will be able to outlast a move of then // skiplist parent). But'''''''<'n'o'i''>'t'p'O' its also very nice having the code run fast forn // small lists. Most lists are small, and it makes sense to optimize forn // that.nn // TODO: For safety, pointers in to this structure should be Pin<> if wen // ever want to hold on to iterators.nn /// The total number of items in the skip list. This is not used internally -n /// just here for bookkeeping.n num_items: usize,n /// Size of the list in user specified units.n num_usercount: usize,nn /// The RNG we use to generate node heights. Specifying it explicitly allowsn /// unit tests and randomizer runs to be predictable, which is very helpfuln /// during debugging. I'm still not sure how the type of this should ben /// specified. Should it be a generic parameter? Box<dyn *>?n /// ??n rng: SmallRng,nn /// The first node is inline. The height is 1 more than the max height we'ven /// ever used. The highest next entry points to {null, total usersize}.n head: Node<C>,nn /// This is so dirty. The first node is embedded in SkipList; but we need ton /// allocate enough room for height to get arbitrarily large. I could insistn /// on SkipList always getting allocated on the heap, but for small lists itsn /// much better to be on the stack.n ///n /// So this struct is repr(C) and I'm just padding out the struct directly.n /// All accesses should go through head because otherwise I think we violaten /// aliasing rules.n _nexts_padding: [SkipEntry<C>; MAX_HEIGHT],n}nnnnimpl<C: ListConfig> Node<C> {n // Do I need to be explicit about the lifetime of the references being tiedn // to the lifetime of the node?n fn nexts(&self) -> &[SkipEntry<C>] {n unsafe {n std::slice::from_raw_parts(self.nexts.as_ptr(), self.height as usize)n }n }nn fn nexts_mut(&mut self) -> &mut [SkipEntry<C>] {n unsafe {n std::slice::from_raw_parts_mut(self.nexts.as_mut_ptr()'''''n '''''''''''''n '''''''''n ''''''''''''''''''''''''''''''''''' 'o't' 'y't's'u'r' 'e'r'o'm' 'e'b' 't'h'g'i'm' 't'I' ':'O'D'O'T' '/'/' '''''''''''&''(*self.here''''''n ''n 'debug_assert'''''''num_item' as usize'''''''''''local_inde'''''''''''e'z'i's'u' 's'a' ''';')'x''''''l'a'c'o'l'.'f'l'e's' '='>' 's'''''''t'i'_'m'u'n'.'e'd'o'n'('!''''''g'u'b'e'd' ''_ptr()';')' '=' 'e'd'o'n' 't'e'l' '.'s's'o'r'''''''e'd'o'n'''''''r'o'g' 'o'n '/''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''':''n /'n ///'''T''' '-' '// ''''''''''' 'y'l'l'''''''''''''''''''''''''''''''''')'s't'n'e't''''''''''''''''''''''''''''''''''''''''''''''''n ///'n ///''''''''''''''''''''''''''''''''''''''''''''''''.'y'r'o'm'e'm' 't'i'n'i'n'u' 'e'r'a'''''''''''' '''''d'o'm' 't'''n'''' 'e'r'a' 's't'n'e't'n'o'c' 'e'h'''t' ','g'' 'n'i't'a'r'e't'i' 'r'e't'f'A' ' ''''.'d'e'z'''' ''e'i'l'a'i't'i'n'i' 't'''n'e'r' ''a' 'r'e'v'o' 'e''''''' ''''''' 'e''''o' 't'a'r'e'''''' 't'i' 'e'w' 's't'n'e't' ''n'o'c' 'e'h'T''n'o'c' 'p'o'r'd' 't'o' ''''''''o't'n' 't'h'g'i'm' 'e'w' 'n'e'h't'(' ''u'f'''''''''n ///'' '-' '''''''''''''''''''d'e'n'i'a'r'd' 't'''n's'i' 'r'o't'a'r'e't'i' 'e'h't' 'f'i''''t' 'e'f'a's'n'u' 's't'I'''''''''''''' 'r'o't'a'r'e't'i' 'e'h'T''''''''''''''a' 's'i'''''''i's' 's'i''''''''''''''''''' 'e'b' '*'t's'u'm'*' 'e'd'i's'n'i' 'h'T' '''''''''''''''''''''''''''''''''''''''s'm'e't'i' 'e'h't' ','n'u'r' 's'a'h' 'r'o't'a'r'e't'i' 'e'h't' 'r'e't'f'A' '.'m'o'r'f' 'l'a'e't's' 'd'n'a' 'm'o'r'f' 'e't'a'r'e't'i' 'n'a'c' 'e'w'''''''''' '{' 'e'f'a's'n'u' 'e'c'''}' 'i'l's''''''''''''i'c'l' 'a' 'e'k'a'M' ''''''' '/'/'/' ''' unsafe fn from'''''''e'b'y'a'''''''''i'''n'U'''''''''<'<''>'t'i''''''''''t'n'i'n'I'e'b'y'a'M'm'_slice(slic'''[0]'''''''''''''''''''''''m'''''''''.'e'f'a'S''''s' '/'/' ''e't'I':':'C' 't'u'm'*' 's'a' '''']'0'['e: &[C::Item]) -> Self {n unsafe {n let ptr = slice.as_mut_ptr();n let end = ptr.add(slice.len());nn UninitOwnedIter {n ptr: NonNull::new_unchecked(ptr),n end,n _marker: PhantomDatan }n }n }n'S''// ''''''''''''''''''.'s's'o'r'g' 'o's' 's'i' 's'i'h'T' '/'// ''/' ', self.hei'''// '('*'ght as usize)n }n }nn fn '// ''''''''''')')'('r't'p'_''''''''''''''''_'t'u''// 'm'_'s'a'.'layout_with_height(h'/''/ 'eight: u8) -> Layout {n Layout::from_s''' }'''i''ze_a'// 'lign(n mem'// '::size_of::<Node<C>>() + mem::size_of'// '::<SkipEntry<C'// '>>() * (he'// 'ight as usize),n mem::align_of::<Node<C>>()).unwrap()n }nn fn alloc_with_height(height: u8) -> *mut Node<C> {n assert!(height >= 1 && height <= MAX_HEIGHT_U8);nn unsafe {n let node = alloc(Self::layout_with_height(height)) as *mut Node<C>;n (*node) = Node {n items: [C::Item::default(); NODE_NUM_ITEMS],n ''#[inline(always)]'n'''''''#[inline(always)]'n' num_items: 0,n height: height,n nexts: [],n };nn for next in (*node).nexts_mut() {n *next = SkipEntry::new_null();n ''#[inline(always)]'n' }nn noden }n }nn fn alloc<R: RngCore>(rng: &mut R) -> *mut Node<'''''n// Stolen from core::mem::MaybeUninit. Its just not standardized yet.nunsafe fn maybeinit_slice_get_ref<T>(slice: &[MaybeUninit<T>]) -> &[T] {n // SAFETY: casting slice to a `*const [T]` is safe since the caller guarantees thatn // `slice` is initialized, and`MaybeUninit` is guaranteed to have the same layout as `T`.n // The pointer obtained is valid since it refers to memory owned by `slice` which is an // reference and thus guaranteed to be valid for reads.n unsafe { &*(slice as *const [MaybeUninit<T>] as *const [T]) }n}n'n'n'C> {n Self::alloc_with_height(random_height(rng))n }nn unsafe fn free(p: *mut Node<C>) {n dealloc(p as *mut u8, Self::layout_with_height((*p).height));n }nn fn content_slice(&self) -> &[C::Item] {n &self.items[..self.num_items as usize]n }nn // The height is at least 1, so this is always valid.n fn first_skip_entry<'a>(&self) -> &'a SkipEntry<C> {n unsafe { &*self.nexts.as_ptr() }n }nn fn first_skip_entry_mut<'a>(&mut self) -> &'a mut SkipEntry<C> {n unsafe { &mut *self.nexts.as_mut_ptr() }n }nn // TODO: Rename to len() ?n fn get_userlen(&self) -> usize {n self.first_skip_entry().skip_usersizen }n n fn get_next_ptr(&self) -> *mut Node<C> {n self.first_skip_ent''r''y().noden }nn /// I dunno where this logic should live, but we want to ''''''''''''''''''''''''''''''''''''':':'t'i'n''''''''''''''''''''''''' 'l'a'e'r' 'e'h't''''''''.'e'l'b'a't's''''MaybeUninit::uninit_arra'''''' 'n'e'h'w' 'y' 'h't'i'w' 'e'c'a'l'p'e'R''''''''''''''''''''s'i'h't' 'n'e'h'w' 't'a'h't' 'l'l'a'C''''R' '.'i'n'U'e'b'y'a'M' '''uninit_array' 'm'o'r'f' 'n'e'l'o't'S' ':'O'D'O'T' '/'/'n'''''''''''p''''''_'s'm'e't'i'ub fn'''>'T'<'''MaybeUnini'''>'T'<'t''''''e'b'y'a'M'' uninit_arr'NODE_NUM_ITEMS''''M'U'N''''X'A'M'ay<const LEN: usize>() -> [Self; 'NODE_NUM_ITEMS'LEN]'M' 'U'{' 'N' 'n'X' 'A' 'M' unsafe { MaybeUninit::<[MaybeUninit<T>; LEN]>::uninit().assume_init() }''n }'o'o'f' 'n'f'n'get the index ofn /// the item at the specified offset i'uninit_items_arra'')'('y'''''n'i'n'u'''nto the node (and the offset into then /// it''// None of the rust builtins give me what I want, which is a copy-free iteratorn// to owned ite''''''''Li'[MaybeUninit::uninit(); NODE_NUM_ITEMS]'stConfig''''''C't's'i'L''''''''''n'o'C' '''':':'C''' ','a'''ms i'n '''''''''''''''''''''m'e't'I':':'C'''''C::Item'''''''' '''e'h't'''''''''''''''''''''''''''.'n'o'i'''t'a't'n'e'm'e'l'p'm'i''''''''e'''>'C'<''m'l'''''C: ListConfig' ','a''''p'e'm'i'''' ','a''''C'''' 't'u'M'r'e't'I''' 'e'r''''''''t''''''''m'e't'I':':'C'''u'M'R'e't'I'''''r'e't'i' ''o'c'''''''''.'e'c'i'l's' 'n'o' 'd'e's'a'B' '/'/' 'n a MaybeUninit array''''''''''''''t'u''''''''''t'u'n'm''''''''''''''''''''''''''.'n'w'o' 'y'm'''''_'''')'''')'t'u'm' 'e'k'a''''k'm' 'o't' 'h'g'u'o'n'e' 'y's'a'e' ''n '_mark'impl<'a, C: ListConfig> 'e'''PhantomData''''a'h'P' ''''''''C' ','a''':'r''''''''''''m'e't'I':':'C''''k'r'a'm'_' ',''s'''''''''''''_' 't'u'm'*' 's'a' 't'i' ';''''.'h'E' '.''''''''''''''''''''''' '''t'''s'u''''''''''''''''''''''''''''''''''''''''''''''''''''''''''d'e'z'i'S' ''':''''>''''>'T'<'T'<'''Unin'''unsaf''' 'e'''''''''''' 'e'f'a's'n'u'itOw''{' ''''''''''''''<'>''t'i'n'i'n'U'e'b'y'a'M'''''''''''''as_ptr()''''_'s'a'.''''''''''.'f'l'e's'''''''n ''''' '' '''''.'f''''''''''.'''''''.',')'('r't''''r'p'_'s'a'''''''')')'('d'a'e'r'l'e's'''''''''n'' '''// ' '' ''''e'n'o'N' 'n ' '''''''''.'r't'p'('e'm'o'S'''' ''' }'n ' '{' 'e's'l'e' '}'n ''''''''''''' '}' 'e'n'o'N' '{' 'd'n'e' '='=' 'r't'p'.'f'l'e's' 'f'i'''''// ' '' 'ne''dIter''U' 'l''''''''' ':'e'c'''''''''''')'('r't'p'_'s'a'.'i'l's''''M' unsafe fn from_slice(slic''e: &[T]) -> Self''''''''>'T'<''''''''''''''''UninitOw'''>'T' '''''''''''''''''n '''''''''''''''''''''''''''''''''''''''''''' ''''e'n'o'N' ''' }''n 'n ' '{' '>'m'e't'I':':'f'l'e'S'<'n'o'i't'p'O' '>'-' ')'f'l'e's' 't'u'm'&'('t'x'e'n' 'n'f' 'n ' ';'T' '=' 'm'e't'I' 'e'p'y't' ''<'nedIte'''''}''n 'n ' '{' 'r'''''n'i'n'U' 'r'o'f' 'r'o't'a'r'e't'I' 'l'p'm'i'n''n' {n '' un''''''''''''''''''''y'p'o'C' ':'m'e't'I':':'C' 'e'r'e'h'w' 'safe {n '' let p''tr = slice.as_ptr();n let end = ptr.add(slice.len());nn UninitOwnedIter {n ptr: NonNull::new_unchecked(ptr as *mut T),n endn }n }n }n'ay'// 'beUnini''''''''''Un'n unsafe fn from''''''f'l'// ''e'S'_slice(slice'// ':'''' &[M'''>'T'<'aybeUninit<T>]) -' '// ' '' unsafe {n l'''''' '// ' let end ='' if me'''''// ''e'c'i'l's'm::size_o'UninitOwnedIter''n ''''U'// ''f:';''':''<T>() == '// '0 {n '// ' 'n '// '''content_slic'')'('e''''''''t'n'e't'n'o'c'.''''''' '''n '''' (pt''}'n 'r a''s *const u8).wrapping_add(self.len()) as *const Tn } else {n'' '' '''''e'c'i'l's''''''' assume(!ptr.is_null());'n'''e''t ptr = self.as_ptr();n assume(!ptr.is_null());nn let end = if mem::size_of::<T>() == 0 {n (ptr as *const u8).wrapping_add(self.len()) as *const Tn } else {n ptr.add(self.len())n };nn Iter { ptr: NonNull::new_unchecked(ptr as *mut T), end, _marker: marker::PhantomData }n }'> UninitOwnedIter {'initOwnedIte''''' }''n 'n ' '{' 'r''''''i'n'i'n'U' '>'''' ''''.'-' ')']'>'T'<'t'''''b'y'a'M'['&'('''p'''''m'''''''''''' '>'-' ''''''i'n''''' u''nsafe fn owned_iter_from_slice<T>'n'''// '''''''Iterator''''''a'r'e't'I' 'l'p'm'i'n'n'''e'e'r'f'-'''''''''''''''''''''''''''''''''''''''''.'y'a'r'r'a' 't'i'n'i'n'U'e'b'y'a'M' ''''''' 'n'a' 'n'i'''''''''''''' 't'''n's'e'o'd' 't'a'h't' 's'm'e't'i' ''''''''''''''''''d'e'n'w'o' 'o't' 'r'o't'a'r'e't'i' 'y'p'o'c'-'o'r'e'z' 'a' 's'i' 'h'c'i'h'w' ','''''''''''''''''''''''''''''''''''''''''''''''''''''''t'''n's'e'o'd' 't'i' 'e'r'e'h'W' '-' '/'/'n's'm'e't'i' 'd'e'n'w'o' 'o't' 'r'e't'I''''''d'e'n'w'O'''''''O'W' '-' '/'/''''''' '-'n':'t'n'a'w' 'I' 't'a'h'w' 'e'm' 'e'v'i'g' 'r'''''''''s'n'i't'l'i'u'b' 'e'h't' 'f'o' 'e'n'o'N''''''''''i'h'T' '/'/'n'em).n /// n /// If'''' th' T: 'a>'', C: ListConfig>'e offset l'n '''''''''''''''''''''''''''''''''''.'s'i'h't' 'o't' 'a't'a'd'm'o't'n'a'h'p' 'a' 'd'd'A' ':'O'D'O'T' '/'/' 'ands '// '''''''''''''''''''''d'e''''''''''''>'a''''' ':'T' ','a'''''''n 'SkipLis'''''''''>'T'<'t'''''p'i'k'S''' '''''''''''''''n '// '''''''''''PhantomDat'''''''>'T' 'a'''&''''*'<'a'''''n'a'h'p''''m' ':'r'e'k'r'a'm'_' ','T' 't's'n'o'c'*' ':'d'n'e' ','>'T'<''''' '''''''''''''<'l'l'u'N'n'o'N' ':'r't'p' '''}''n 'n ' '{'''''''''n '{' 'n'w'O'''''r'e't'I't'i'n'i'n'U''''''''i't'i'n'I' 't'c'u'r't's''n'n'n'between items, we could return either the previous or next item.n /// n /// Returns (index, item_offset).n fn get_iter_idx(&self, mut usersize_of''fset: usize, stick_end: bool) -> (usize, usize) {n if usersize_offset == 0 { return (0, 0); }nn for (i, item) in self.content_slice().iter().enumerate() {n let usersize = C::get_usersize(item);n if usersize > usersize_offset {n return (i, usersize_offset);n } else if usersize == usersize_offset {n return if stick_end { (i, usersize_offset) } else { (i+1, 0) }n } else {n usersize_offset -= usersize;n }n }n panic!('Could not find requested offset within the node');n }n}nnstruct NodeIter<'a, C: ListConfig>(Option<&'a Node<C>>);nimpl<'a, C: ListConfig> Iterator for NodeIter<'a, C> {n type Item = &'a Node<C>;nn fn next(&mut self) -> Option<&'a Node<C>> {n let prev = self.0;n if let Some(n) = self.0 {n *self = NodeIter(unsafe { n.first_skip_entry().node.as_ref() });n }n prevn }n}nn/// This is a set of pointers with metadata into a location in the list neededn/// to skip ahead, delete and insert in items. A cursor is reasonably heavyn/// weight - we fill in and maintain as many entries as the height of the listn/// dictates.n///n/// This is not needed for simply iterating sequentially through nodes and data.n/// For that look at NodeIter.n///n/// Note most/all methods using cursors are unsafe. This is because cursors usen/// raw mutable pointers into the list, so when used the following rules have ton/// be followed:n///n/// - Whenever a write happens (insert/remove/replace), any cursor not passed ton/// the write function is invalid.n/// - While a cursor is held the SkipList struct should be con'''n '''''''''''''''''''''''' '''''t's'n'o'c'':'e'd'o'n'''''' bool''''''''l'o'o'b' '>'-' ''''' ''''e'd'o'n''' ''is_head = n as *const _ == &self.head as *const _''' }''n 'n ' '{' ''''''''''''')'>'C'<'e'd'o'N' 't'n '// '''''''print(';')''''i'r'p'.'f'l'e's' ''u'm''''m'*''''&' ','f'l'e's'&''''*'('d'a'e'h'_'s'i' 'n'f' 'n ' 'sidered pinned andn/// must not be moved or deletedn#[derive(Copy, Clone, Debug)]nstruct Cursor<C: ListConfig> {n // TODO: Add a phantom lifetime reference to the skip list ro''' /// The global user position of the cursor in the entire list. This is usedn /// for when the max seen h'''''''('!'g'b'd'e''ight in')'creases, so we can populate previouslyn /// unused entries in the cursor and in the head node.n ///'n ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''e'n'o'N''''if cfg!(debug_assertions''''Some(SmallRng::seed_from_u64(seed)''' '}' ')' '{' ''')''None'''''' 'f'i'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 's'e'i'r't'n'''''''''''''''' /// When the userpos of an ent'_'ry is 0 (totally valid and'''' ')'','i'(' usefu''enumerate()'''''m'u'n'e'.'l), a cursor' /// becomes ambiguou'n 'paren''''''''nul''''t'','u'm'_'l()'''''l'l'u'n':':'r't'p' ':'t''''''n'e'r'a'p' 's with regard to where exactly its pointing in then '' /// current entr'''''.'f'l'e''')'n'(''s'y. This is use'''''''''''''''''''''''''''.'y't'i'u'g'i''''u'b'm'a' 't'a'h'''self.''t' 'e'v''''''''.'f'l'e''''')'n'(''s'l'o's'e'r'''''''''''a't''n '''''''''''''''''''''''''''''''' '{' 'e'f'a's'n'u''as_pt''''}' ')'('r''''_'s'a''''a'.''''*'''''''''''''''''''.'''''''''''''''''''''''''''n 'if cfg!(debug_assertions'''n ''''''init_rng_from_seed''''''n '3'2'1''''1''' '''''''{' 'e's'l'e' ' ''}'n '''''.'f'l'e''')'n'(''s' ';''2'3'(seed:'=''''''''''d'a'e'h''''''.'e'd'o'n'''''''t'h'g'i'e'h''''''''''''''''''e'z'i's'u' 's'a' ''''''''''''''''u' 's'a' 'd'a'// ''e'h'.'f'n 'println''''''''''''''''''}'?''''n as *const _' ',':'{' ''''''';')'i' ','''}'{' '// ''''g'n'i't'i's'i'v'''('!'''''n'i'r'p' ''l''''.'e's'''''''// '-''''>''' ' dbg!''((n as *con''st _, (*n).height'// '));n'u64)''' '''// ''''// ' }'n ''''''' '// ''(''n'''d'// 'bg!(n.p''''''''''''// '''')'t'h'g'''i'e'// ''h'.')'n'*'('''''''('*' ','arent);n'n ''''&'''''''''''''''''''''n dbg!(n.parent);''n dbg!(&self.head as *const _);'_' 't's'n'o'c'*'''''''*'&' 's'a' '''d'a'e'h'.'f'l'e's''''''''''''''''n ';')'t'n'e'r'a'p'.'n'('!'g'b'd' '''t'i'n'i'.'f'l'e's' '{' ''') { Some(SmallRng::seed_from_u64(seed)) } ' '.'e'l'b'a't's' 'e'r'a' 's't's'e't' 'e'h't' 'o's' 'e'd'o'm' 'g'u'b'e'd' 'n'i' 'G'N'R'''''''R'N' 'e'l'b'a't's' 'a' 'e's'u' 'l'l'''e'W''''''''''''''''''''''''' ','e'd'o'm' 'g'u'b'e'd' 'n'i' 'e'r'''e'w' 'f'I''''W' '/'/' ' 'e'l'v'o's'e'r' 'o't' ''''''' 't'd'n /// becomes ambiguous''''''''''''''o't' '''''''''y'l't'c'a'x'e'''''''''''''''''''''y'r't'n'e' 't'n'e'r'r'u'c' 'e'h't' 'n'i' '' 'd'r'a'g'e'r' 'h't'i'w''''''t'u'o'b'a' in where '''''''''''''d'e's'u' 's'i' 's'i'h'T' 'its pointing.'n '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'g'n'i't'n'i'o'p' 's't'i' 'e'r'e'h'w' 'n'i' 's'u'o'u'g'i'b'm'a' 's'e'm'o'c'e'b' 'r'o's'r'u'c' 'a''''' 'e'h't' ',')''''n '''''''''''''''''''''''''''''''''''''''''''','8'u''''8' ':'t'h'g'i'e'h' ''n ''''''''''''''''&self.head as *const _ as *mut ';'_' '=' 'r't'p'_'d'a'e'h' 't'e'l' '''''''''''''''e'''' for entry'''' 't'u'm' in &mut self.entries[0..height as usize] {' ''''''''t'e's'f'f'o' e''''''8''''9'u' 's'a' 'nt'''n 'ry.skip_'' // Dirty hack. If n has 0-sized elements at the end, the normaln // cursor won't be at th' while normal_iter.here_ptr() != ''''''''''''''''''''''_' 't'u'm'*' 's'a' '_' 't's'n'o'c'*' 's'a' 'n {' normal_iter.advance_node();' }n'' 'n'n'' 'e end..'n 'normal_ite''loca''l_''inde''''''num_item'''''n '''''''normal_ite''here_ptr(''''''''n 'normal_ite''advance_nod''''' }'n ';')'('e''''''n'a'v'd'a'.'r'''''''l'a'm'r'o'n' '{' 'n' '='!' '''''get_userle''' ')'('n''''''u'_'t'e'g'.')'.'r''''''a'm'r'o'n''''(' 'e'l'i'h'w' ''''''''';'e'z'i's'u' 's'a' '''' 's'''''_'m'u'n'.'n''''normal_iter''''''a'm'r'o'n' '=' 'x'''''a'c'o'l'.'r'''''m'r'o'n' '.'n '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'.'.'d'n'e' 'e'h't' 't'a' 'e'b' 't'''n'o'w' 'r'''' 'o's'r'u'c' 'l'a'm'r'o'n'''''''r'o's'r'u'c' 'e'h't' ','d'n'e' 'e'h't' 't'a' 's't'n'e'm'e'l'e' 'd'e'z'i's'-'0' 's'a'h' 'n' 'f'I''''''''''''' 'e'h'T''''''''o'n' 'a' 'f'I' '.'k'c'a'h' 'y't'''''''t'e'r'i'D' '/'/' 'users'''''t's'n'o'c'ize'-'''n ''''''''''''''''''''''null_mut('''MAX_HEIGHT''''X'A'M'''''''''n ';']''''n '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''n '''(''''''''''''''''''''''''t'e's'f'f'o'_'l'a'c'o'l''''')'_' ',''''''n 'a''''''''''''''''')''''>'m'e't'I':':'C'''''''''':'''''n '' ''''''''''''''''''''''''ManuallyDro'''''''''''';')'m'e't'i'('w'e'n':':'p':':''''o'm'e'm':':'d't's''''''''l'l'a'u'n'a'M' '=' 'e'u'l'a'v'.'t'o'l's' '':'T' ','_'(''// ''''_' ':''''('''''''''m'e't'I''''''''''''''''')'m'e't'I':':'''''''''''''''''''''''''''''''''''''''''''''''''.'e'u'l'a'v' 'd'l'o' 'e'h't' 'p'o'r'd' 't'''n'o'd' 'e'w'''''''' 't'''n'o'e'w' 'e'r''''''''''w' 'e'u's' 's'e'k'a'm' 'e't'i'r'W'''''''''''''''''''' 't'''n'o'd' 'e'w' 'e'r'u's' 'e'k'a'M' '/'/' ''''C' 't'u'm'*' 's'a' '':':'C' ':'ssert_eq''''''''''''''''0''''get_userle'''';')')'('n'''''''''''e'l'r'e's'''u''as_mut_pt'')'('r''''':':''''''''''>'m'e't'I':':'C'<''''''''_'t'u'm'_'s'a'.''''''''''''')'''('e't'i'r'w'.''_'''''''u')'t'e'g'.'n' ','t'e's'f'f'o'_'l'a'c'o'l'('!'''s'a' ''''''''''' '{' 'e'f'a's'n'u' '=' 'r'e't'i'_'e'd'o'n' 't'e'l'''''''ite''}'n ''''''''''''''''''''''''iter_at_userpos''''''''''''''n 'assert_eq''''''''''''''''''''''''';')'r'e't'i'_'e'd'o'n' ','r'e't'i'_'l'a'm'r'o'n'('!''''s's'a' 't''n let node_iter = unsafe { self.iter_at_node(n, n.get_userlen(), n.num_items as usize) };';''n'u'o'c'r'e's'u'_'''''''''''''r'e's'u'm'u'n'(target_userpos: usize)'.'f'l'e's' '=' 'r'e't'i'_'l'a'm'r'o'n' 't'e'l' '' 'r_at_nod'''''''''e'z'i's'u' 's'a' 'e'n'''''''''''''''')''''num_items';''''''''t'i'_'m'u'n'.'n'('n'e'l'r'e's'u'''''''o'l'_'t'e'g'.'n'(mut n: *mut Node<C>, mut offset: usize, local_index: usize)'''''r'e't'i'.'f'l'e's' '.'s'e'h'c't'a'm' 's'n'o'i't'c'n'u'f' 'r'o't'a'r'e't'i' 'e'h't' 'y'b' 'd'e'n'r'u't'e'r' 'e'u'l'a'v' 'e'h't' 'k'c'e'h'C' '/'/' 'n ' '''')'_' ';')''''l'u'n':':'r't'p''''''_'l'l'u'n''''''''[''*mut Node'''MAX_HEIGH'''''[' '=' ']'T''''X'A'M' ';'<C>' ':'''' 'v'e'r'p' 't'u''head_ptr''''''_'d'a'e'h'm' 't'e'l' '' += usersize;' }n'' 'n'n'' '' ''''''use''rp''o''''''''''''''' 'n ' for entry in &mut self.entries[0..height as usize] {n entry.skip_usersize += usersize;n }' ';'t'e's'f''''s'f'o' '='-' 's'''''r'e's'u'.'f'l'e's' ''' }''n 'n ' '{' ''z'i's'u' ':'t'e's'f'f'o' ','')'f'l'e's' 't'u'm'&'('t'r'a't's'_'m'e't'i'''''''''''''e'd'o'n'_'o't'_'e'v'o'm' 'n'f' 'n ' 'l'u'f'e's'u' 'd'n'a' 'd'i'l'a'v' 'y'l'l'a't'o't'(' '0' 's'i' 'y'r't'n'e' 'n'a' 'f'o' 's'o'p'r'e's'n ''''''local_inde''''';'0' '=' 'x''''''l'a'c'o'l'.'f'l'e'''n '''''''''''''''''''''''''''''' 't'u'm''' as *const _'''''''''''''''' ''''''''''''''';'m'e't'i' '=''?''' 't'o'l's'''*''' (slot as *mut C::Item).write(item); // Do not call drop() on junk.n'''''' '_''// ' '('''' as *mut C::Item)''('''''''''''''''''''''m'e't'I':':'C''''''''''''''''')'''''''''''''''''''''''''''''''.'k'n'u'j'''''t'n'o'c' 'n'o' ')'('p'o''''a'r'd' 'l'l'a'c' 't'o'n' 'o'D''''N' '/'/' ''''('e't'i'r'w'.')''''('_' 't'u'm'*' 's'a' ' '''_'''f'l'e's''''' ''i''''''''''(''''''here_ptr()'''''e'r'e'h'.'f'l'e's'''''e'r'e'h'''' '{' 'e'f'a's'n'u'''''''''''''''8'u''''''e'z'i's'u''''''''-'e'z'i''''z's' ':'t'h'g'i'e'h' ',''n'f 'se''''''n ''''''''''''''''m'e't'i'_'t'n'e'r'r'u'c'''''''''''''''unsaf'''n ''''''''' 't'u'm'''''y'r''''''''''''''''' '''''''''''''''f: &mut fmt::Formatter<'_'''''''''''Resul'''''v'e'r'p'''' '''''''''d''e''bug_struct'''''''r''' .field('userpos', &self.userpos)n'n ' '''''''''''''''''x'e'd'n'i'_'l'a'c'o'l'''''n ''' '/'/' '''''''x'e'd'n'i'local_index''''''l'a'c'o'l'''''''''_''''''''''''''''''''''''n 'mut ''''' ''finis''h_non_exhaustive('''')''''''''''o'n'_''')'('h's'i'n''''e'n'o'N''''i'f'.' ')'s'o'p'r'e's'u'.'f'l'e's'&' ','''s'o'p'r'e's'u'''('d'l'e'i'f'.' ' 'o's'r'u'C'''(name: &st'''r)'''''u'b'e'd'.'f' ''' }''n 'n ' '{' 't'''''u's'e'''R':'n '// ''''''''''''';'n' '=' ']'i'['v'e'r'p' '':'t'm'f' ''n '''''''''''''''''''''''''''''''''n ''''''nul'''''''''''''''''''''''''''''''l'l'u'n' 's'i' 't'n'e'r'a'p' 's'''d'a'e'h' 'e'h'T' '/'/' 'l''_''m''ut()'''''l'l'u'n':':'r't'p' '''''''''''''''''''''''''''''''''''''''''d'a'e'h' 'o't' 'k'c'a'b' 't'n'i'o'p' 's'e'd'o'n' 't'h'g'i'e'h' 'x'a'M''''''' 't'''n'o'D' '/'/' ''' '{' 'd'a'e'h'_'s'i' 'f'i''' ''''''''''''_' 't's'n'o'c'*''''''''''''''''''''t'n'e'r'a'p''''a' 'd'i'l'a'v'n'i''' ','' 's'a' ' ' ' '''''' 'e'''s'l'e' '}'n '''''''''''''''''MAX_HEIGHT_U'''n '''''''(''''''' ''''&self.''''''n ''''''''n ''''''_' 't'u'm'*' 's'a' 'h'n ''''n ';''''ead as *const'expect_parent' '''e'p'x'_;''''''')'''''as'e'_mut_pt'')'('r''''_'s'a'.''''''''''' '{''iter[n.height as usize].nod''}' 'e' 'e's'l'e' '}' 'd'a'e'h'.'f'l'e's'&' '{' '8'''''''T'H'G'I'E'H'''''''''' '// ' let walk_height = (*parent).height as usize - 2;n''''A'M'_'E'D'O'N' '='=' 't'''''''''''' as usize''''''''''''''''e'z'i's'u' 's'a' '1' '-' 't'h'g'i'e'h'.')'n'*'(''''h'g'i'e'h'.'n' 'f'i' '=' 't'n'e'r'a'p'_'t'c'e'p'x'e' 't'e''maybeinit_slice_get_ref''''''''''''''''''e';''c'i'l's'_'t'n'e't'n'o'c'_'t's'e'd'(slice: &[MaybeUninit<T>])''''''e'b'y'a'm'l' ''n '''// ''a'!''''''''''''''''''''''''''''''''''''''e'd'o'n'.''';')']'e'z'i's'u' 's'a' 't'h'g'i'e'h'.'n'['r'e't'i' ','t'n'e'r'a'p'.''''''''''o't'n'i'.'n'(entry.''n'ssert_eq'''''''.'y'r't'n'e'('!''''''r'e's's'a' ''''''n '''s's'a' '>'-' ')'>' ','f'l'''e's'&'('t'm'f' 'n'f' ''ListConfi'''''''''''''''''''''''''''''''n '''}'n '{' '>'C'<'r'o's'r'u'C' 'r'o'f' 'g'u'b'e'D':'''''''''''' ','f'l'e's' ' ''''''''''''''''('e'm'o'S' '=' 'g'n'r'.'''''d'''';'''''n fn get_rng(&mut self) -> &mut '_'SmallRng {n '''&mut self, '''//'_'n '''''''''''''''''''''''''''''''''''''''''''''''''''.'e'n'i'f' '''''''.'e'n'f'i' 's'''''''s' 't'i' 't'n'e'r'a'p' 'e'h't' 's'a' 't'h''''I' ','g'i'e'h' 'e'm'a's' 'e'h't' 'e'r'''e'w' 'f'&mut '''num_items: usize, ''''num_items: usize, '''&mut '''''''' ''''''''''''''''''''','''e'z'i's'u' ':'s'm'e't'i'_'m'u'n' 't'u'''''''''r'o't'a'r'e't'I''''''''''''' 't'u'i'm'&''''7''I''''I''W''''''''''r'e'h't'i'e' ''''''''''''''''''t'o'l's''''''''''ExactSizeIterator'''''c'a'x'E'''''''''''''''''' ',''n ''''''''''''''''''''''''''''''''''''''''.' '' (slot.as_mut_ptr('') as *mut'' C::Item).w'n '''''dest_content_slic''' '=' 'e'''''t's'e'd' 't'e'l' 'rite(item);n''d'e'v'o'm' 'y'// ''l'n'o' 'e'r'e'w' 'y'e'h't' '-' ''''''''''''''''.'s'm'e't'i' 'd'l'(slot.as_mut_ptr() as *mut C::Item).write(item);''o' 'e'h't' 'p'o'r'd' 't'o'n' 'o'D'''''''''''''''''''''''''''''''''.'m'e't'i' 'd'l'o' 'e'h't' 'p'o'r'd' 'o't' 't'n'a'w' 'o'd' 'e'W' '/'/' 't'n'e'r'a'p' 'e''''''''r'o't'a'r'e't'I''h't' 's'a' 't'h'g'i'e'h''''''''''e'i'h''' '''''''''Exact''size_hint(''0'.')'''''e'z'i's'''// 'Size'// 'Iterato''''''''''''''>'m'e'''t'I':':'C'='m'e't'I'// ''<'r''''a'x'E' ':''''''''// 'I''''''''''n 'n '' '' '''''''''''''''''''''''''''''''''num'';')'('n'''e'l''''NODE_'.'s't'num_item''');''''''''NODE_NUM_ITEM'';')'S''''''_'E'D'O'N' '='<' 's''''m'u'n''n'e't'n'o'c' '=' 's'm'e't'i'_'m'u'n' 't'e'l' ''n ''''''''('!'t'r'e's's'a' ' 'debug_assert''''''''''''''''''''num_item'';')'s''''''''e't'i'_'m'u'n' '='''' '>' ')'('n'e'l'.'s't'n'e't'n'o'c'('!''''''g'u'b'e'd' '''s'm'e't'i'_'m'u'n'' ''''n ','e'm'a's' 'e'h't' 'e'r'''e'n ' ' ' '(''self.is_head(')'';'''''pa'' '// ' '' // debug_assert_eq!(, );'n''''n'ren''''(*parent).height a'// 's usize''='=''' > h' '&'&'t')')'' ''|''| ''''' '|'|' ''w' 'f'I' '/'/' '' I'm s''ure ther'''''''' item' i''new_nod''''''''''''''''''''''''''''t'u'm'_''')'('r'e't'i'.''''''''''''''')'s't'n'e't'n'o''n '''''new_userle''''C::userlen_of_slice(new_node.content_slice('''';''')'''))''// ' '=' 'n' 't'e'l' '// ''c''''''''r'u'''c'('p'''i'z'.']'s'm'e't'i'_'m'u'n'n ''''''''n ''''''''''''''''''''''''''''''''''''''''''''''' 't's'a'e'''''n''''''''''''''''''''''''''''''''''''''n '''!'e't'a't's' 'd'i'l'a'v'''n'i' 'n'a' 'n'i' 'e'r'''''n ''' '' // debug_assert_eq!(new_userlen, C:'new_nod''''''''''''''e'c'i'l's'_'t'n'e't'n'o'c'''''''')'('s'm'e't'i'.'''''''i'.'e':''w'e'userlen_o'n'f_slice(conte''nts));n'e'w' ''n // TODO: Make sure the iterator wrote at least num_items. If not, we're in an invalid state!','t'n''o'n' 'f'I' ''n'.''l' 't'a''''''''''s'm'e't'i'_'m'u'n' 'e't'o'r'w' 'r'o't'a'r'e't'i' 'e'h't' 'e'r'u's' 'e'k'a'M' ':'''''''''' ':'O'O'D'O'T''''D' '/'/' 'n ' ''''''''''''';'m'e't'i' '=' 't'o'l's'*''''(' ''.'.'['s'm'e't'i'.'e'''''_'w'e'n' 'n')''''''''''''''''' 'n'i' ')'m'e't'i' ','t'o'l's'('''''''t's'n''''''is_head''''''t'''|'|' ''n'e'r'a''n '''''num_it''''ms''''''contents.len(';')' '=' 'n'e'l' 't'e'l' 'p''''num_it''''ms''n'e'l'''''''''''''num_items''''''i'_'m'u'n'.'.'0' 'n'i' 'i'''''''''''''next(''unwra'')'('p'''''r'w'n'u'.')'''e'n'.'s't'n'e't'n'o'c''i'''''''''''''t'n'e'r'a'p'('''''''it'''''''''''''s''n '''''''''''''''''''''''' 'new_node.items'0'''''''';'m'e't'i' '=' ''''[..contents.len()]' ''' }''n 'n ' '{' 's't'n'e'''''''''n ''''''''''''''''''''''''''''''''''>'T'<''''('e'c'i'l's'_'m'o'r'f'_'r'e't'i'_'d'e'n'w'o''''O' 'n'f' 'e'f'a's'n'u' 'n ' ''t'n'o'c' 'n'i' 'm'e't'i' 'r'o'f''''''r'o'f' '''''n 'n ' 'iz''size_'// 'hint''''; //contents.len() ''''''n'e'l''size_hint(' '''';')''''z'i's'.'s't'n'e't'n'o'c'''''''t'i' '(''/'/'node: *const Node<C')'>)'''''h'_'s'i'.'f'l'e's''''p'' ''o'c'e's a nicer way to implement this.n if self.rn'n '''''''' 't''''''''''''>'C'<'e'd'o'N'''''''''''''''''''''''''''''''.'r't'p' 't'u'm' 'a' 'd'e'e'n' 'e'w'''''''''''''''' 't'u'b' 'copy''''''''e'n'o'l'c'''''.clone()''''','''''e't'a't'u'm' 't'''n'''''''''''')'('e'n'o'l'c'.'' '// ' // unsafe fn insert_node_at<Notify>(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item], new_userlen: usize, move_curs''or:'''nd_no''' 'ify'bool, mut notify: Notify)' '' '' unsafe fn insert_node_at(&mut self, cursor:'' &mut C'''' 't'u'm'ursor'&'<C>, contents: &[C::Item], new_userlen: usize, move_cursor: 'n 'num_items''''''i'_'m'u'n' // unsafe fn insert_node_at<Notify>(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item], new_userlen: usize, move_cursor: bool, mut'num_items' notif'i'y'_':'m'maybeinit_slice_get_ref''''''(slice: &[MaybeUninit<T>])''''y'')'a'm'' '' 'u'Notify)'bool) {'n'n'' '' '''' 'n'' ''o'd''' 'e'W' '// ' unsafe fn ins''ert_node_at(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item], new_u' 'serlen: usiz'// 'e, mo''ve_cursor:'// ' bool)' '' '' 'n unsafe fn insert_node_at(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item], new_userlen: usize, move_cursor: bool) {' unsafe'' fn in''sert_node_and_notify<Notify>(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item], new_userlen: usize, move_cursor: bool, mut' ' notify: Notify)n where Notify: FnMut(&[C::Item], ItemMarker<C>) {n' {n'' '/'/' ''''n '''' ''''''';'_' 't'u'm'*' ''new_node.content_slice()'s'a' 'n'u'm''''' '''=' 'n' 't'e'l' '''g''.is_no'''n 'ne'n if parent.is_null() { bre';'''ak; }'() {n '' self.rng = ''S'n debug_assert!(('n debug_assert!((*parent).height '''I' ','as usize > h);'*pa'n'rent).height as usize > h);'''''I' 't'u'm''ome'n'(SmallRng::from_entropy());n '''''''''''''')'('t'u'm'_''' ''''''''', I: ExactSizeIterator<Item=C::Item>' ','s't'x'e'n'.''' '' 'n // Reached the head.' }n self.rng.as_mut().unwrap()n }n'n 'SmallRn''''''''''''''''';')'('y'p'o'r't'n'e'_'m'o'r'f':':'g''''''l'l'a'm'S' 'e'e's'''f'''''l''''''n ''''''' 'e'f'a's'n'u'''''''''''''''''' 't'u'm''n''''''''''''''''''''''''' 't'u'm''''''''''''''''''''''''''e'z'i's'u' ':'x'e'd'n'i'_'l'a'c'o'l' ','''''''''e'z'i's'''u''' '''''''''''''''''''''_'e'z'i's' ':'// ''t'e's'f'f'''''''''''''''''''''''''.'r'e't'a'l' 's'i'h't' 't''''''''''''','x'e'd'n'i'_'l'a'c'o'l'''''''''''X''''''''''''''''''''''''''''''''''''''''''''''''''''''''''')'n'i' 'd'e's''''e's'a'p'''''n '// '''''''''''''''''''''''n '''''''''''''''n '''''''n '''''''''''(*n).heigh''''''''''''' '' cursor.entries[h] = SkipEntry {' 'n node: n,' 'n '''n ''n '' ''''n ''''''''''n '''''''''''d'l'u''''''''''''o't' 'e'l'b'a' 'e'b' 'o'h'S'''''''n ''''''''''''''''''''.'d'a'''''' '''// ' ''' 'new_nod''''r'''t'p'_'e'''''''o'n'_'w'e'n''' '' '' '// ' ' ' if height > 1 {' 'n '' '// ' let mut n = e;'' ' '' 'n '' '// ' // let new_parent = cursor.ent''''_'w'e'''n'''''r''i''e''s[h' 'eight - 1''].node;n'// '' 'n // If you imagine thi' '' '// ' 's node as a big building, we n''eed to''' '// ' 'n '' /' '// ' '''/ update the pa'// 'rent of all the node''s we cast a shadow'// ' ' 'over.' '' 'n '// ' ' '' // Can't use copy_within because we aren''''' 't'u'm'&''t su'':':''''>'C'<'re if the typen // implements Copy. Memmove the existing items.'n ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.' ptr::copy(n &c'item_idx'[offset_bytes],n 'item_idx + num_inserted_items' &mut c[offset_byt''''''''UninitOwnedIte'':':'''r''UninitOwnedIt''''''''''''''('e'c'i')''l's'_'m'o'r'f'.'''e'''''''''>'C'<'r''''''i'n'i'n'U' '''''s'm'e's''''''t'''i'_'''''''''x'd'i'_'m'e't'i'm'u'n'.'''e''s + num_inserted_bytes],n (*e).num_bytes as usize - offset_bytes);''s'm'''''''m's'e't' 'n ''''''''''''''''''''''''''''''''''''['c' 't'u'm'&''item_idx..item_idx + num_';'inserted_items]' '=' 'e'c'i'l's'dest_content_slice'''''t's'e'd''_'t'n'e't'n'o'c'''''_'t's'e'd'''''_'w'e'n' 't'u'm''''n''''w'e'n' 't'e'l' ' // Then copy in the new ite'''item_id'''item_id''''num_inserted_items''''m'u'n' '+' ''contents'''''t'n'o'c'x'''''m'e't'i'.'.'']'x'''''m'e't'i'['c'''ms. Can't memcpy from an iterator, butn // the optimizer should make this f'dest_content_slice'''''t's'e'd'ast.''i' 'g'n'i't's'i'x'e' 'e'h't' ''''''''''.'''''''''''''''''''''''''''''''''''''''''''''''''''''n ''''''''''''''''''''''''''''''C::userlen_of_slice'&''''item_idx..item_idx + num_inserted_items]'['c'''(contents);' '=' 't'n'u'o'c'r'e's'u'_'d'e't'r'e's'n'i'_'m'u'n' 't'e'l' ''''''''''''''''''''''.'t's'a'f' 's'i'h't' 'e'k'a'm' 'd'l'u'o'h's' 'r'e'z'i'm'i't'p'o'''''t's'u'r' 'e'h't'''''e'p'o'h' 't'u'b' ','r'o't'a'r'e't'i' 'n'a' 'm'o'r'f' 'y'p'c'm'e'm' 't'''n'a'C' '.'''''' '' ''n 'n for (cell, item) in into.it' 'er_mut' '().zip' '(iter) {n ' ' *cell = item;n }' '' '// ' ''d'a'e't's'n'dest_content_slice'''''t's'e'd''i' ' ptr::copy(' 'n &c[leading_bytes + removed_bytes],' 'n &mut c[leading_bytes],' 'n 'n '''''''''''''''''''''''''''''''''''''''''s't'n'a'w' ''''''''''''''''''''''''''''''''''''''// '''''''''t'''''''''t'u'm'_''')'('r'e't'i'.''o'l's' ''' '' '// ' '*slot.as_mut_ptr() ='inserted_conten''next('''''''''';''''''';'''/')'// ''('p'a'r'w'n'u'.''''(')''''x'e'n'.'t'''''''t'r'e's'n'i''' item;' ''''''''''''''''''''t's''' ''e'd' 'n'i''''''' '=' 't'o'l's' 't'u'm'&'''''''' 'n'i' 'i' 'r'o'f'''''''n '''''' ''' }''n 'n ' '{' ' 'index..index + replaced_items_here' '/':' 't'n'e't'n'o'c'_'d'e't'r'e's'n'i' 'f'o' 'p'i'h's'r'e'n'w'o' 's'e'k'a't''''''s'e'v'i'g' 't'i' 't'u'b' ')'('p'i'z' 'e's'u' 'o't' 'r'e'f'e'r'p' 'd'l'u'o'W' '/'/' ' trailin'// 'g_bytes);''''e'v'o'm'm'e'M''''M' '.'y'p''''&'o'C' 's't'n'e'm'e'l'p'm'i' '// ''e'p'y''maybeinit_slice_get_ref''''')'''(slice: &[MaybeUninit<T>])'''''b''// 'y'a'm'' 't' 'e'h't''''i' 'f'i' 'e'r'u's' 't'''n'e'r'a' 'e'w' 'e's''' ptr::cop'''_'y(n &c'''''('*'''i'as_mut_ptr'''''''''D''''''''p'_'t'u'm'_'s'''''''''d'e'c'a'l'n ''''''''''''maybeinit_slice_get_ref(dest';')' '=' 't's'e'd' 't'e'l' ''p'e'r'a't'''''''''')'('t'u'm'_'t'e'g'.'em_idx + rem''''t's'e'd''maybeinit_slice_get_ref(dest)'''oved_here''leading_bytes + removed_bytes'''item_idx'''''''i'_'m'e't'i'it'trailing_items''''''''n'i'l''maybeinit_slice_get_ref''''')'''(slice: &[MaybeUninit<T>])'''''' 'b'y'a'm'i'a'r't'em_idx + removed_here'[leading_bytes + removed_bytes],n &mut c[leading_bytes],n trailing_bytes);'' 'n ' ptr::copy(' 'n &c[item_idx],' 'n &mut c[item_idx + num_inserted_items],' 'n (*e).num_items as usize - item_idx);' 'u'a'c'e'b' 'n'i'h't'i'// ''w'_'y'p'o'c' 'e's'u' 't'''n'a'C' '/'/' ' ' c[..].copy_within(item_idx..e_num_items,n item_idx + num''_inserted_items);n' '' 'n '' '''// '/''/ So, if'' o't'u's'r'e' height ' '// ' ';' 'd' 'is 3 a'// 'nd the next nodes 'maybeinit_slice_get_ref(dest)'have heights 1' ' '''new_node_ptr'''''''o'n'_'w'e'n''' ' 'n '// ' // and 2, they bo' 't''h need new parents.' '// ' 'n l' '// ' '' 'et mut skip_height = 0;n' '// ''// ' 'n '// ' loop {' ''' ' ''// '// ' 'n ' ' // dbg!(skip_height);' '// ' 'n ' '// ' ' // dbg!((*n).height as usize);n' 'n ' ' n = (*n).nexts_mut()[skip_height].node;' 'n ' ' if n.is_null''('') || (*n).height >= height as u8 { break; }' '.'''''''''e'w' 't'u'b' ',''' 'n ' ''''''''''''num_''insert'ms'ed'r'_ite'aining'm''''num_inserted_item''n '''''''''num_''insert'ms'ed'r'_ite'aining'm'''''''n ''''''''''''''''''''''''''''n'''i'm''''''''n'ms'um'r'_ins'aining'erted_item'''NODE_NUM_ITEM'';')'S''''M'U'N''''''''''X'A'M' ','s'''u'n'('x''insert_here''''''r'e's'n'i'n '''num_''insert'ms'ed'r'_ite'aining'm'''''insert_her';'e''''''r'e's'n'i' '='-' 's''''m'u'n' ''a'm''''M':':'e'z'i's'u' '=' 'e'r'e'h'_''''+'t'r'e's'n'i' 't'e'l' ''' '' ''''''' }' 'content'' ','s''''''''t'n'e't'n'o'c' '''''n '' '// ' 'n 'n' ' '{' '0' '>' 's'''' 'n }' '''''_'m'u'n' 'e''// 'l'i'h'w' ';'s'''''_'m'u'n' '=' 's'''''_'m'u'n' 'n // for chunk in contents.take(NODE_NUM_ITEMS) {' '' 't'u'm' 't'e'l'// ''n // TODO: We could cac'n // ''''''')'('r'e't'i''''t'.' // let userlen = C::userlen_of_slice(chunk);''n // self.insert_node_at(cursor, chunk, true, notify);'he this each time t'// 'he height goes up?' 'n (*n).parent = cursor.entries[(*n).height as usize + 1].node;' 'n skip_height = usize::max(skip_height, (*n).height as usize - 1);' 'n }' 'n }''''''''''n 'n ' 'n ' 'n ' 'n ' ''e'h' 'e'h't' 'd'e'h'c'a'e'R' '/'/' ''''''''''''''''''''''''''''''''''''''''''''}' ';'k'a'e'r'b' '{' ')'('l'l'u'n'_'s'i'.'t'n'e'r'a'p' 'f'i'''n '''n '''''''''''''''''''.'l'l'u'n' 's'i' 'n' 'f'''''''''''t''''e'k'a't''n'e'r'a'p' 't'' '// ' debug_assert!((*parent).height as usize > h);'''''' '' '' ' // Walk fr''om parent back to n, fig'n ''''''''''''''''' offset;''''''''''';'t'e's'f'f'o' '=' 's'o'p'r'e's'u'.'r'o's'r'u'c' 'uring out the of'''' 't'u'm'fset.' let c = parent;n'n'n'n'n'''''''n 'let'''''''''''t'h''2''''1''''2'''g'i'e'h'_'k'l'a'w' p_'''I' ','heig''ht''''''''''''' '''''''''=' 'm'e'l'e' ''n ', mut inserted_co''''''I' 't'u'm''''M'&'''ntent: &[C::Item]'', I: ExactSizeIterator<Item=C::Item>' ''''''''''''''''''''skip_usersiz';'e'''', I: ExactSizeIterator<Item=C::Item>'''''''''', I: ExactSizeIterator<Item=C::Item>' ','''''u'_'p'i'k's'.'m'e'l'e' '='+''' 't'e's'f'f'o' ''n '''''''''''''''';'e'd'o'n'.'''''''.'e'm'e'l'e' '=' 'c' ';''t'e'l' ='' (*parent).height as usize'walk_heigh']'t'''''''''i'e'h'_'k'l'a'w''' - 1;' ''e'l'i'n 'debug_assert''inserted_conten'''''''''''replaced_item'';')'s'''''''c'a'l'p'e'r' '='>' ')'('n'e'l'.'t'''''''''''''n'o'c'_'d'e't'r'e's'n'i'('!'''''u'b'e'd' '' 'k'c'e'h'c' 'd''''''''''''''su''''''''''''''''1'(*parent).height'' '-' 'e' as usize''z'i's'u'''''''u's' 's'a' 'n''a'e't'''''''t'n''''''''n ''''''''''t'h'g'i'''''e'h'_'p' ''''''''''''''''''''''''''''''n'''n '''''local_inde''''local_index.expect('Invalid marker - item not found in'' n'// 'ode'';')' '=' 'x'''''''''n'i'_'l'a'c'o'l' 't'e''local_index''''''l'a'c'o'l''''''''''''o'''l''''='o'l' '''n ' ' ' ' ''' '''' '''c'''' 't'u'm':'''''':''&':'C'''''''''.f''''''''''''t'''' 't'''u'm'&'''''''''''''' ' '' '' ''n ''''''''''''''''''''C::userlen_of_slice''(ol''d_it''em't's';')' '=' 'e'z'i's'r'e's'u'_''''''''''i's'_'d'l'o' 't'e'l' ''''' let new_items = &inserted_content[0''..r''epla''ce't'd_items_here];n''' let new_usersize = C::userlen_of_slice(new_''i''tems);n 'd' 's' let'' usersize_delta = new_usersize as isize - C::use''rle''n_of''_s'd''t's''lic''e(old_items) as isi' let new_items ='old_item';'s''od' '(*e).items''''(*'''&inserted_content[0..replaced_ite'old_usersize''''''u'_'''d'l'o'ms_here];n'ze;nn'''''n // unsafe fn insert_at_iter_and_notify<Notify>(&mut self,'' 'n ' let new_usersize = C::userlen_of_slice(new_items);n let usersi'// 'ze_delta = new_usersize as isize - C::userlen_of_slice(old_items) as isize;nn' ' cursor: ''&mut Cursor<C>, contents: &[C::Item], mut notify: Notify)' '','g'i'f'n'o'c'.'f'l'''''''f'.'e's'''''':'c' ''self.iter_at_node(n, of'n // ' 'w' '' 'he''' let new_items =''inserted_content''''(*'''&(*e).items[0..replaced_items_here];''od''old_item''';'s'''d'o' ''''''''''s'm'e't'i'.')'e'*'('''''''*'(''''inserted_content'''&inserted_content[0..replaced_items_here];n're Notify: FnMut(&[C'd'::'s'Item''], ItemMarker<C>) {'fse'local_index.expect('In'' 'n ' let new_usersize = C::userlen_of_slice(new_items);n let usersize_delta = new_usersize as isize - C::userlen_of_slice(old_items) as isize;nn' 'valid m'' 'n ' '''''''''s'm'e't'i'_'d'l'o''' for (slot, item) in new_node.items[..num'''''''''''''''''''''''''''''''''''''.'t'n'e't'n'o'c' 'd'e'v'o'm'e'r''''' 'd'l'o' 'e'h't' 's'p'o'r'd' 's'i'h'''''''s'i'T' '/'''''''''''''n'I' '/'/' ''''''' '/'''''''''''''''''''t'n'e't'n'o'c'_'d'e't'r'e's'n'i'_items].iter_mut().zip(contents) {' 'n *slot = item;' 'n // (slot as *mut C::Item).write(item); // Do not call drop() on junk?' 'n }' 'n' 'arker - item '// 'not found in node')'''''t, local_ind'''n 'ex)' d'n // Now we need to make a cursor at''''''''''''''''''''y'p'o'C''''''e'n'o'l'C' ':'m'e't'I':':'C' 'e'r'e'h'w' ' the node/userpos location pair.n let mut cursor = Cursor {n userpos: 0,n '' local_index: local_index.expect('In'''n ''''''''''''''''''ItemMarke'''' ''''''new_nod'''''''' 't'u'm'&''''n '''''''''''''''d'e'i'p'o'c''''''''')'('d'e'n'o'l'c'.')'('r'e't'i'.''''''''''o't'n'i'.'_phanto'''PhantomData''Ph''Phan';'tomD''ata'''h'P' ':''';''m'''nn fn no_notify(_items: &[C::Ite' // unsafe fn insert_at_iter_and_notify<Notify>(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item], mut notify: Notify)' // where Notify: FnMut(&[C::Item], ItemMarker<C''''''''''''''''''''y'p'o'C' ':'m'e't'I'''' ':':'C' 'e'r'e'h'w' '>) {' '' 'n'' 'n'' 'm], ''_marker: ItemMarker<C>) {}'''''h'p'_' ','r't'p'_'e'''''''o'n'_'w'e'n' ':'''r't'p' ''''' '// '')'}''n 'n '_and_notif'<Notify>(&mut self, cursor: &mut C'&mut''''''''s't'n'e't'n'o'c' inserted_content.iter().copied()'ursor<C>, contents: &[C::Item], mut notify: Notify)n '// ' where Notify: FnMut(&[C::It''_'y''' '' '' '' '' '' '' '' ''''' '''{' 'r'''''m'e't'I''''M' ','s't'n'e't'n'o'c'('y'f'i't'' where Notify: FnMut(&[C::Item], ItemMarker<C>) 'n''''''o'n' 'n ' 'valid marker - item not found in node'),n entries: [SkipEntry {n node: &self.head as *const _ as *mut _,n '''''''n 'unsafe fn insert_node''''''''''''''''''>'y'f'i't'o'N'<'y'f'i't'o'n'_'d'n'a''''''''''':':'r'e't'i''' '&mut contents.iter().copied()''t'u'm'&'''''''''''':':'r'e't'i':':'d't's''''''('e'c')''''n'o'''''''''_'''_''at(&mut self, cursor: &mut Cursor<C>, contents: &''[''''''', mut notif'n ' ''where Notify: FnMut(&[C::Item], ItemMarker<C>)'''n ''''''insert_node_at''''''r'''''''''s''''''''''''n''''''''''''r';''o's'r'u'c'_'e'v'o'm'e'l'r'e's'u'_'w'e'n't'n'e't'n'o'c'o's'r'u'c'(cursor: &mu'&mut iter::once'''d'n'e'(start)'t Cursor<C>, contents: &[C::Item], new_userlen: usize, move_cursor: bool)'''''''t'r'e's'n'i'.'f'l'e's''' ' {' 'y:')''' ''N''' }''n 'n ' 'otify' ','C::Item], new_userlen: usize, move_cursor: bool) {' 'n ' ' '''n '''''''''''''''''''':''''' ','s'm'_''''''''' ':'r'e'k'r'a'm''e't'i'_'(&[C::Item], ItemMarker<C>'''}'{' ')''''('y'f'i't'o'n'_'o'n' 'n'f' 'n ' 's'n '''fn notify(&mut self, _items: &[Self::Item], _at_marker: ItemMarker<Self>)'/'/' 'kip_u'// 'se''''''i't'o'n''''''''''''y'f'i't'o'n'_'d'n'a'_'rsize: usize::MAXn }; MAX_'''' 't'u'm'HEIGHT],n };nnn for i in 1..self.hea'n uns'''''''y'f'i't'o''''o'N'''''>'F'<'''''''>'F'afe fn insert_at_ite''''''''''''''''y'' 'n ' '''''''''''''''C'''''''ItemMarker'C'<Self>' ',''''''':':'c''''''''''''''''''''']'m'e't'I':':'f'l'e'S'['&' ':'s'm'e't'i''''''''''' ')'('t'u'M'n'F' ':'y'f'i't'o'N' '''''''''' ':'y'f'i't'o'n' 'e'r'e'h'w' ''' ''f'i't'o'N' ':'y'f'i't'o'n' ','r(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item]) {'d.height as usize {n n = (*n).parent;n // And find the local offset. Noten }n unimplemented!();''''n ''''''iter_''iter_at_node'mut n: *mut Node<C>''n''mut offset: usize'''''''t''local_index: usize''''''''''''x'nn cursor''''e'd'n'i'_'l'a'c'o'l'e's'f'f'o'(mut n: *mut Node<C>, mut offset: usize, local_index: usize)''''''_'r'e't'i'.'f'l'e's' '''ebug_assert!((*parent).height as usize > h);'''''n';'t'h'g'i'e'h'.')'t'n'e'r'a'p'*'(' '=' 't'h'g'i'e'h'_'p' 't'e'l' 'n ' 'e'r'''''''''''''''''''''y'p'o'C' ':'m'e't'I':':'C' 'e'r'e'h'w' 'a'p'''s'n'i' 'd'l'u'o'C' '?'?' '/'/' 'n ''''''''''''''''''''''''''''''''''''''''''''''''.'e'r'e'h' 't'n'i'a'r't's'n'o'c' 'y'p'o'C' ':'m'e't'I' 'e'v'o'm'e'R' ':'O'D'O'T' '/'/'n''''''''''''''''''''''''''' ','''g'n'i''''n' 'o'''n ' where C::Item: Copy' ''''''''''''''''n '''''''''''''''' '''''''''''''''''''''''''y'p'o'C' ':'m'e't'I':':'C' 'e'r'e'h'w' '''''''''''''''''''''''''''''''''''''>'m'e't'I':':'C''''<'<'c'e'V' ':''''2''''1' '-' 't'h'g'i'e'h'.')'c'*'('[''''''''''''<'''''''''''>'m'e't'I':':'C''''<'<'c'e'V' ':'s't''''s'x'e'n'.')'c'*'(' '=' 'c' ''' }''n 'n ' '{' 'n' '='!' 'c' 'e'l'i'h'w' ';'t'n'e'r'a'p' '=' ''''u'c''''i' 't'e'l' '.'t' 'k'c'a'b' 't'n'e'r'a'p'''''''p'b' 'm'o'r'f' 'k'l'a'W' ' ' ''''''''''''''''''''''''''''''n 'n '// ' ' ''''''''' '// ' 'n ' let mut n = new_node_ptr;n loop {n n = (*n).nexts_mut()[new_height_usize - 2].node;n 'n ''''''print(';')''''i'r'p'.'f'l'e's' ' 'n 'if cfg!(debug_assertions) {'''''''''v'n'''}' 'e' 'f'i'' '''''''check(';')'''''c'e'h'c'.'f'l'e's' ' if n.is_null() || (*n).height >= new_height { break; }nn (*n).parent = new_node_ptr;n }' '.'n' 'o't' 't'n'e'r'a'p' 'm'o'r'f' '''''''n ''''''''''';'t'n'e'r'a'p' '=' 'n' 'n ' ''''''''''''''''''''''.'t'e's'f'f'o' 'e'h't' 't'u'o' 'e'r'u'g'i'f'''''''p'u' 'd'n'A' '/'/' '''''''''''';'1' '='+' 'h' ''''''''' '''' '''''' '''n 'debug_a'n'ssert'''''''''''''''''''''e'z'i'n n = (*n).parent;''s'''''u' 's'a' ''''''''''' 's'a' ''';')'h' '>' 't'h'g''n debug_assert!((*n).height as usize > h);'i'e'n''h''n'.')'n'*'('('!''''''g'u'b'e'd' ' ' ' skip_''' '' n = (*n).''''n '''''n 'n ' ''n ''''''''''''''''_' 't's'n'o'c'''''''''''''''''' '''_' 't's'n'o'c'*' 's'a' '*' '''s'a''n''d_no' 'ify''''''''''' 's'a''''''&''''''''''''''''''''''n '}' ';'k'a'e'r'b' '{' '''d'a'e'h'.'f'l'e's' '='=' 'n' 'f'i' 'parent;''''n 'n ' 'usersize: offset' '// ' 'n };' 'n''' '// ' }''n 'n '// ' ' '{' 'e'z'i's'u''' '''''s'a' ''''n ''''''''''n '''// ''''''''''''ItemMarke'''' ''''''''n '_phant'm'o'''PhantomData' ':'n''';'_''''PhantomData''''a'h'P' ','e' ':'r't'p' ''''' '' 'nd_no' 'ify' ')'}''n '' 'n ' '{' 'r'''''m'e't'I''''''r'a'M' ','s't'n'e't'n'o'c'('''notif'''('y''''''f'i't'o'n' 'y'f'i't'o'N' '/'/' 'n ' 't''// ' '<' 'h' 'e'l'i'h'w''' '''''''n 'println'''''''''''''''''''''''''''''''''''}'{' '''t'h'g'i'e'h'''''''h'e' '}'{' 's't'n'e't''' '// ' 'n ' ''?':' ''?':' println!('remo''''''content_slic''''''''''t'h'g'i'e'h' ',')'('e''''n'o'c'.')'e'*'('vi''ng {} contents {} height {}', e, );n' ''''n 'n'o'c' '}'{'''''''''''''''' '''s't'n'e't'n'o'c''' ',''';')'e'' '''' ','''g'n'i'v'o'm'e'r'''('!'''''n'i'r'p' 'n ' ' }'n ' ''// '{' 'p'o'o'l'''''''l'i'h'w' ';'// ''0' '=' 'h' 't'u''''m'm''''' '=' 'h' 't'e'l' '''// ''''n 'n ' ''''''n '' ''''''''''''''''''''' 't's'u'j' 'n'e'v'e' 'd'l'u'o'C' '/'/' '''''n ''''''''''''''''''''''''''''''''''{'' ' 'e'z'i's'u' 'h''''s'a' '' 't'h'g'i'e'h'.')'n' '' ''*'('.'.'0' 'n'i' 'h'' ''' 'r'o'f''' }'n ''heigh''t''''''i'e'h''''e'''''''h'g' 'n ' ';'0' '=' '' 'n 'for h in 0..(*n).height as usize { ' ' 't'h'g'i'e'h' 't'u'm' 't'e'l' '' 'e'b' 't's'''' 'n cursor.entries[0] = SkipEnt''ry {'arent'' '1''' '0''''1''' 'n node'n ''''''''''''''''''''''''''here_ptr(''n ''''''''''''''''''''''''''''''''e'z'i's'u' 's'a' '''n 'if height >= cursor_node_height '''n '{''''if h'''''''''''''' 'arent' ' } else {n'' els' {'e'}''eight >= cursor_no''d''e_'n cursor_node'heigh'''if'height''''geug''(*n)'n } else {'.height as usize''geug';''''n '''' height >= cursor_node''''1' '-' '_height {'t '''n '' 'arent' '{' ';''' '' '''''''''''{' 'e's'l'e' '}''''''''' 'new_parent = ''' '' ''''''''t'h'g'i'e'h'''''''''''''g'u''''';' '''''n ''e'g''(*n).height as usize' if n_height >= cursor_node_height {' ''''1' '-' ' 'n '' '' '''''' '''''a''r''ent' ne''''1' '-' 'w_par''ent = cursor.ent''r''i''e''s[skip_height + 1].nod''e' 'arent' 'n '' 'arent' }'''''''''''''''''''''''''''';'e'd'o'''''n'''''_'r'o's'r'u'c' '=' 't'n'e'r'a'p'_'w'e'n' 't'u'm' 't'e'l' '''''cursor_nod'''heigh'''''''''''';'e'z'i's'u''' 's'arent''a' 't''''i'e'h'.')'e''''''o's'r'u'c'*'(''''*' ''''''''1' '-' ''=' 't'h'g'i'e'h'_'e'd'o'n'_'r'o's'r'u'c' 't'e'l' ';')'''''e'r'e'h'.'r'o's'r'u'c' '=' 'e'd'o'n'_'r'''''n ''''''''''''''''''''''''''';'t'h'g''''''''''e'z'i's'u' 's'a' 'i'e'h'.')'n'*'(' '' 'n ' let n_height = (*n).height;' ''=' 't'h'g'i'e'h'_''''-'n' 't'e'l' ''o's'r'u'c' 't'e'l' ''n ''''''''1' '-' ' '' '' ''''''''''''''''''''// '''''''e'z'i's'u' 's'a' ''''' '='>' 't'h'';')''g'i'e'h'_'n''skip_height''''// '''p'i'k's'('!'t'r'e's's'a' ': n,' ''// 'n '''''''''''''''''''''''''''''''// ''// '''''''''''''''e'e'r''''n 't' '''''s't'n'e'r'a'p' 'e'// ''h't' 'p''// 'u' 'k'l'a'w''' 'o't' 'd'e'e'n' 'e'w' '// ''w'''''''''t'''h'g'i'e'h'_'n'o'N' '''// '' '/'/' ' '''n '// ' ' 'n 'i'// 'nsert'// ''''// '_''node_''and_no''tif''y(curso'// 'r: &mut Cursor<C>, c'''' no' ' skip_height = n_height - 1;''n'''' - 1''' '' '' '' ' '' '' ' (*n' ').parent = if '''// 'curso''r_' '' ' ' }' 'n }' '' ' ' '' 'n'' ' ' ' '' ' 'node_'/''''1' '-'' - 1''' ''''''' 'n skip_height = n_height - 1;' ''''/ 'height >' ''' (*n).''height '' '// '{' ' '''''1' '-' ' '' '' '' '=''' '// '''cursor_node' ' ' 't' ' + 1''''''h''''''' 'g' '''i' 'e' 'h' '_' } else {' '// ''n' ''''1' '+''''''' '-' ' '// ' '// ' // TODO: ''We should be able to cache this each t't'i'// 'me'h'''n ''''''''''''''''// ''''''''e'z'i's'u'' '' '// ' 'if'n_heigh' 't'''' '='>' cursor_nod' '// ' ''''''''''''''cursor.entries'skip_height'''''''h'_'p'i'k's'[n_height a'// 's usize].node' '=' 't'n'e'r'a''// 'p'_'w'e'n' 'e_heigh''t''''''''='''<''' > ''''' '// ' 'new_paren';'''t'''''''a'p'_'w'e'n''' }''n 'n ' '{' 'n_height' ' 's''''' 'skip_heigh''''''''''''''''''''''''n ';'e'z'i's'u' 's'a''''=' 't'h'g'i'e'h'''''''i'e'_'n' '=' 't''''''_'p'i'k's' ''' }''n 'n ' '{' 'a' '''''skip_height'''''''''i'e'h'_'p'i'k's' '>' 't'h'g'i'e'h'_'n' 'f'i' 'n ''n n '' assert_e'''n 'n ' 'q!((*n).parent, e);n (*n).parent = '// 'if cursor_node_height > n_height {n cursor_noden } else {n // TODO: We should be able to cache this each timen // the height goes up.n cursor.entries[n_height as usize].noden };nn skip_height = usize::max(skip_height, n_height as usize - 1);''g' 'i' 'e' 'h' '_' // the heig'n'ht goes u'.'p'n'n'n'' 't''''''''''''''''''''''c''' 'o't' 'e'l'b'a' 'e'b' 'd'l'u'o'h's' 'e'W'ify','ontents: &[C::Item], new_userlen: u''si''ze, move_cursor: bool, mut n''otify: Notify)' skip''_usersize: offset' 'n };''' 'cursor_n''ode_heigh''''''''''''''''''n '''// ' ' } else {n' '' 'cursor_node'''''''r'o's'r'u'c' ''' 'e''' '' '' '' '' '''''''''''{' 'e's'l'e' '}'n 'n } else {''n cursor.entries[(*n).height as usize + 1].node' '{' 't'h'g'i'e'h'.')'n'*'(' ''' ';' }'n '''='>' 't'''''''r's'o'r'u'c' 'n '' for i in 1..'insert_node'at'_''insert_node_and_notif'(cursor: &mut Cursor<C>, 'C'contents: &[C::Item], new_userlen: u''size, move_curs'n ''' 'f''// 'i''n ' ' ' // TODO: We could cache this each time'''''' }'n ' the height goes up'''n '?'or: bool, mut notify: Notify)'''y(cursor: &mut Cursor<C>, c''''''''''''y'f'i't'o'n' ','ontents: &[C::Item], new_userlen: usize, m'''n 'o''''v''e_cursor: bool, mut notify: Notify)'self.hea'''and_no''tify'''d.''he''i''ght'' a'n's usize {' 'n '' notify',''' '// ' n 'n if n.is_null() || (*n)'// '.height >= height as u8 { break; }'= ('n'*n)''.pa''n n = (*n).nexts_mut()[skip_height].node;'''''''n 'nn fn'' no_notify(_items: &[C::Item], _m'n dbg!((*n).content_slice());'arker: ' dbg!((*n).con'n dbg!((*n).height);'ten'n't_slice());n'ItemMarke'// 'r<C>) {}' 'rent''*''''''t''''n ''''''n ''''''''is_head''''''''t';''n'e'r'a'p'.'n'(nod'e'''e: *const Node<C>)''''_'s'i'.'f'l'e's' 'h'g'i'e'h'''')''(';' 'n ''''''''content_slic'''assert_eq'''''''''''''''n'''''';')'e' ','t'n'e'r'a'p'.')'n'*'('('!''''s's'a'''n '';')')'('e'''''''''_'t'n'e't'n'o'c'.'n'('!'g'b'd' ' 'n '' '' // And find the local offset. Note' '// ' 'n }'''''n 'n ' ''''''n ''''''r'o's'r'u'c'// '' 'n ';' ' 'n ' 'u'j' 'd'l'u'o'h's' ''''''' 's'i'h't' 'e'b'y'a'M'(' '.'r'e'l'l'a'c' 'y'b' 't'e's' 'e'b' 't's'u'm''''t'e's' '/'/' '''n 'if cfg!(debug_assertions) { self.check(); }' 'n ' '''A'M':':'at'''''''''''''y'f'i't'o'n'_'d'n'a''''''e'''''z'i's'u'''e's' 'l'l'''e'W' '/'/' ''o'''''''''''y'f'i't'o'n' ','''''i's' ',''''''''''''''''''' ' ' ''''''''''''''''''';'0' '=' 't'e' ''s'f'f'o' 't'u'm' 't'e'l' ''' 'n // No''';'w we need to make a cursor at the node/userpos location pair.n ' 'let mut cursor = Cursor {n ' ' userpos: 0,n local_index: local_index.exp' 'ect('Invalid marker - item not found in node')' ',n entries: [Skip' 'Entry {n node: &self.head as *const _ as *mut _,n skip_usersize: usize::MAXn }; MA'// 'X_HEIGHT],n };''''Curso'''>'C'<'r'''''''' // If you imagine this node as a big building, we need ton // update the parent of all the nodes we cast a shadow over.n // So, if our height is 3 and the next nodes have heights 1n // and 2, they both need new parents.'' ''''''''''''''''''''''''''''''''''''''''''''''''''n '// ''dbg''skip_heigh'''n '// '''''''(*n).height as usiz'''''n ';')'e'('!'g'b'd' ';')'t''''''_'p'i'k's''''''''''k's'''('!''''g'b'd' ''''''''''''''''''''''''''''''''''''''''''''''''''skip_height'''''p'i''n '''''''''''''''''d'l'u'o'''''''u'p'c'''''''''''''''''''''''''''''''''''''''''''''?'p'u' 's'e'o'g' 't'h'g'i''''i'e'h''''r'u'c' 'e'h't' 'e'm'i't' 'h'c'a'e' 's'i'h't' 'e'h'c'a'c' 'n'a'c' 'e'W' ':'O'D'O'T' '/'/' 'k's''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' (*n).parent'cursor.entries'(*n).height as us'''1' '-'ize''skip_heigh''''1' '+'' ' 't'''''p'i'k's'[height - 1''''''''''''skip_heigh'' ','t''m':':'e'z'i's'u'''].node' = new_parent;n'n'''''''''''''''''''''''''n 'skip_heigh''''skip_heigh'''''''''''''''''''''''''''''e'z'i's'u' 's'a' '''''''''''''''''''u's' 's'a' ''';')'t'h'g'i'e'h'.')'n'*'('('x''''p'a'm'.'t''''''_'p'i'k's'''''''''''x'a'm':':'e'z'i's'u' '=' 't''''''_'p'i'k's' '''''''''''''''''''''''''''' 'e'h'T' '.'s't'n'e'r'a'p' 'w'e'n' 'd'e'e'n' 'h't'o'b' 'y'e'h't' ','2' 'd'n'a' '1' 's't'h'g'i'e'h' 'e'v'a'h' 's'e'd'o'n' 't'x'e'n' 'e'h't' 'd'n'a' '3'''''''''' ','2' 's'i' 't'h'g'i'e'h' 'r'u'o''''w' 'f'i'''''''e'n' 'e'h't' ','o'S' '.'r'e'v'o' 'w'o'd'a'h's''''s' 'a' 't's''''n'a'c' 'e'w' 's'e'd'o'n' 'e'h't' 'l'l'a' 'f'o' 't'n'e'r'a'p' 'e'h't''''''''''''''s'e'd'o'n' 'e'h't' 'l'l'a' 'e't'a'd'p'u' 'o't' 'd'e'e'n' 'e'w' ','g'n'i'd'l'i'u'b' 'g'i'b' 'a'''''''e'b' 's'a' 'e'd'o'n' 's'i'h't' 'e'n'i'g'a'm'i' 'u'o'y' 'f'I'''''''''''''''''''''''''''''''''''''' 't'a'h't' 's'e'd'o'n' 'e'h't' 'l'l'a' 'e't'a'd'p'u' 'o't' 'd'e'e'n' 'e'W' '/'/' ''' '''''''''''''''''''''''';'0''''-''''''';'1' '=' 't'h'g'i'e'h'_'p'i'k's' 't'u'm' 't'e'l' '''''''n 'n ' 'n ' 'n ' ''o's'r'u'C' '>'-' ''''''>'C'<''''''' }''n 'n ' '{' ')'e'd'o'N' 't'u'm'*''''&' ':'e'd'o'n' ','f'l'e's' 't'u'm'&'('e'd'o'n'_'t'a'_'r'e't'i' 'n'f' 'b'u'p' 'n ' ''''''''''''='='='=''')'e's' ''''''<''''Q: Queryable>''''''''Queryabl'>'e'<''''('''''''''''''''>'e'l'b')''''a'y'r'e'u'Q' 's'a' ''''<''''''''''''''''')'''''Queryabl'>''''>'e''''''y'r'e'u'Q' 's'a' ''''''''''''' 's'a' 'm'e't'I':':'C'(''''''''r'e'u'Q' ':'Q'<''SmallRng::seed_fro''''''''Queryable'''''r'e'u'Q''y'r'e'u'Q':':'Q'''m_u64(123)''t'u'm'&':'t'm''''n ''''''''''''''''''''''''''''''''''''''''' }''n 'n ' '{''''-' ')'4'6''''''''''''e'f'a's'n'u'''''''u'p' ''''''' 'e'f'a's'n'u''u' ':'d'e'e's'('d'e'e's'_'m'o'r'f'_'g'n'''''''''''''''''''r'f'_'d'n'a'r'_'t'i'n'i''''I' 'n'f' 'b'u'p' 'n ' 'f' '>'g''''s'n '''n 'unsafe f'mut '''n insert_at_ite''r<Notify>(&mut self'''' ''''''insert_at_iter_and_notif'''''('y'.''''''''''S''''''''':':'f'l'e's':':'f'l'''''';''F'e'S''insert_at_iter_and_notif''''''''''''''''''''''''''no_notif'''';')'''y''')'(_items: &[C::Item], _marker: ItemMarker<C>)'''o'n' ','s't'n'e't'n'o'c' ','r'o's'r'u'c' ','f'l'e's'('y'''''''''a''' '// ' 'n ' unsafe fn insert_at_iter<Notify>(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item], mut notify: N'// 'otify)' 'n where Notify: FnMut(&[C::Item], ItemMarker<C>) {n'''''''''>'y'f'i't'o'N'<' '_'t'r'e's'n'i' ''' }''n 'n ' '{' ', cursor: &mut Cursor<C>, ''''''''''''''''''''y'n ' ' '''''''Notify: FnMut(&[C::Item], ItemMarker<C>) {''' 'e'r'e'h'w' ' ' ''''f'i't'o'N' ':'y'f'i't'o'n' 't'u'm' ','contents: &[C::Item''], notify: Notify)' 'n ' ' ''''''''t'u'm' '''''{' 'e'f'a' 'n '''''''' 't'u''''''''''''''n ''''''''''''''''''''''''''';'e'n'o'N' '=' 'x'''' ','')'''')'i'(''e'd'n'i'_'l'''''''')'('r'e't'i'.'a'c'o'l''''''''''enumerat'')'('e'''''m'u'n'e'.'''''''''';'e's'l'a'f' '=' 'd'n'u'o'f' 't'u'm' 't'e'l' ';'0' '=' 'e'z'i's'u'''''''i's'''''''s'i' ':'m'''''''''';')'i''''''u'm''t'e's'f'f'o' ''''''_'local_inde''''''''('e'm'o'S' '=' 'x'''''''_'l'a'c'o'l''''m'e't'i't'e'l' ' ''s'n''''''n'u''n '' '' ''''''''''''''''''''''''local_inde''expect''''''(msg: &str)'''''e'p'x'e'.''''''''n''''' 't'u'm'u'.'x''''''l'a'c'o'l''''u' '=' 'x'e'd'n'i'_'0'''''''''t'e's'f'f'o''''l'a'c'o'l' 't'e'l''''''''''''';'local_index.expect('Invalid marker - item not found in node')''[SkipEntry {' 'n node: &self.head as *const _ as *mut _,' 'n skip_usersize: usize::MAX' '''n '''''''''''''''''''''SkipEntr'''' '''''''''n 'skip_usersiz''''''''t'e's'f'f'o' ':'e''''''''''''i'1''''s'r'e's'u'_'p'i'k' '''''''''''''''''n '''''''n '''''''''''''''''''ItemMarke'''' ''''''','e' ':'r't'p' '''n ''' '';'_phanto'''PhantomD','ata''''h'a'P' ':'m''_' ''' ')'}''n 'n ' '{' 'r'''''m'e't'I' ','s'm'e't'i'_'w'e'n'('y'f'i't'o'n' 'n ' ' ''''''''''''''''''''''''''''''''''e't'o'N' '.'t''n 'unimplemented''';')'('!'''n'u''''// ''''''''''''''h'j'f'd'k's'a'h'j'f'''d's'a''// ' 'e's'f'f'o' 'l'a'c'o'l'''''''t'e's'f'f'o' 'e'h't' 'd'n'i'f' 'd'n'A' '/'/' ';''''r't'n'e'r'a'p'.')'n'*'('''''''.'n' '=' 'n' ''s' ','n''' '' ':'''' 'e'''d'o'n''// ' ''' ';'}''n 'n ' '{' 'y'''''p'i'k'S' '=' ']''''n 'n notify(new_items, ItemMarker {n ptr: e,n _phan''tom: PhantomData,n '// ' });' '0'['s'e'i'r't'n'e'.'r'o's'r'u'c' 'n '' ' ''''n '// ' '''''''''''''''''''''''''heigh'''''''''''''// '''' ''' }''n 'n ' '{' 'e'z'i's'u' 's'a' 't''''i'e'h'.'d'a'e'h''''''''''i'e'h'.'f'l'e's'.'.'0''''0' 'n'i' 'i' 'r'o'f' 'n '''' 't'u'm' ' ' '&' 'n ''''''r'o's'r'u'c''''''''''''''r'c' 'n'r'u't'e'r' }; MAX_HEIGHT],'''' 'n node: &self.head as *const _ as *mut _,' 'n '' 'n ' skip_usersize: usize::MAX'''e'u'r't' '=' 'd'n'u'o'f' '''''' '''''''''''y'f'i't'o'n' ','''''''''item_offse''n '''''';'k'a'e'r'b' ';'t'''''m'e't'i' '='+' 't'e's'f'f'o'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''n ''''''''''''''''''''''''''''''''''''''''''''''/'e'd'''''''''' 'n'o'n '''''curso''''''''''''n ''''''''''''n 'local_inde'''','0' ':'x''''''''''d'n'i'_'l'a'c'o'l' ','0' ':'s'o'p'r'e's'u' ''''''''>'C'<''''' ''''''''''']'[' ':'s'e'i'r't'n'e''''en'e't''eprin'n ''''''''''collection'''HashMa';'p'''''h's'''''t'u'''''''u'i'm' 'a'H':':'s''n '// ''ptr_to_i'''''''''''''''''''null(''''''''''''X'A'M':':'e'z'i's'u''''''''';')'1'-' ',')'''''l'l'u'n':':'r't'p':':'d't's''''''''':'r't'p'('t'r'e's'n'i'.'d''pt'''o't'_''''.'r''''r't'p' '''''HashMa'''new(';''''''')'(')''''w'e'n':':'p''''''''p'a'M'h's'a'H''l'l'o'c':':'d't's' 'e's'u' ''''n'n '''''''''''''''''''''' '=' ')'d'i'('e'm'o'S' 't'e'l' 'f'i''ptr_''{' '''' '''to_i''g' 'et''('&'''''''''' print!(' (parent: {})', id);' }n'' 'n''''''''''''r'e''?':''''''''''''''''''_' 't's'n'o'c'*' 's'a' 'e'd'o'n't'n'''i'o'p'''n '''''''''''''''''''''''' '{' 'X'A'M':':'e'z'i's'u' '='=' 'd'i' 'f'i'''''f'i' ''''''''''''' }' '''n if let Some(id) = '''n ''n 'println''';')'('!'''''n'i'r'p' 'ptr_to_id.get(&(node.parent as *const _)) {' ''n ';')'d'i''''n print!('(parent: {})', id);'''''')'''_' 't's'n'o'c'*' 's'a'n }'' '''''''''''''''''_' 't's'n'o'c'*' 's'a' 't';''n'e'r'a''''o'p'.'e'd'o'n'(k: &Q)'''e'g'.'d''''r't'p''' 'ptr_to_i''insert''''''''''''''''_''i';'' 't's'n'o'c'*' 's'a' 'e'd'o'n'(k: K, v: V)''''''r'e's'n'i'.''''''''''e's'.'d''''n '// '''''''''''r't'p' 't'e'l' 'f'i' ''n ''''''''''''''''''''''' ','''';''')''''}'}'{' ':'t'n'e'r'a'p'('''('!'''' 't'n'i'r'p' ''r't'p' ' '''''''''''''''''''d't's' '=' 'd'i'_'o't'_''''T'r't'p' 't'e'l' 't!''''t'n'e' ''' ';'}''n 'n ' '{' 'r'o's'r'u'C' '=' 'r''''''''o's'r'u'c' 't'e'l' ''''''n 'n f'''''''':':'f'l'e'S''n'''''''y'f'i't''''f'o'n'_''''n'o''no_notify(_items: &[C::Item], _marker: ItemMarker<C>)'''o'n' ','n no_notify(_items: &[C::Item], _marker: ItemMarker'''n '<C>) {}' ''i't'a'c'o'l'''''r'i'a'p' ''o'n' ''''''''''.'s'o'p'r'e's'u' 'e'h't' 't'a' 'r'o's'r'u'c' 'a' 'e'k'a'm' 'o't' 'd'e'e'n' 'e'w' 'w'o'N' '/'/' 'n ' 'e'd'o'n' 'n'i' 'd'n'u'o'f' 't'o'n' 'm'e't'i' '-' 'r'e'''''''e' 'k'r'a'm' 'd'i'l'a'v'n'I''''M''' ',''';')'d'n'u'o'f'('!''''('t'r'e's's'a'''' ' ''i'L'''''''''''''' 't'u'n '''''''''''''n '''''''''''''''''''''''''''''''''''''''''''''''t'n'e'r'r'u'C''''T''''' 't'u'm' '.'d'n'u'o'f' '&''t'''''Self::no_notify' ',''''Self::no_notify''n's'i' 'm'e't'i' 'e'h't' 'f'i' 'c'i'n'a'P'''''o'r'h'T' ':'O'D'O'T''''''''''D'O't' '/'/' '''get_usersize''''m';''e't'i'(_item: &Self::Item)':':'C' '='+' 't'e's'f'f'o' ''''''''''''' }'n '{' 'e's'l'e' 'n'*'(''m''')'*'&'''''''''''''''''''''' '=' ')'t'e's'f'f'o'('e'm'''''' ''' }''n 'n ' '{' ''o'S' 't'e'l' 'f'i''''n' ''''''contains_ite''''''')'y'r'e'u'q'('m''contain''''' 'e't'''u't'm''i'_''''('s'''''''&''''s'''Self::no_notify' ',''n'i'a't'n'o'c'.'m'e't' ''i''t' ' 'u' 'm' ''''''''''''''&''''''''Self::no_notify' ',''content_slic'''''''' '''' '' ''' 'unimplemented''';')'('!'''''m'i'n'u' 'n ' 'n ' }''n 'n ' '{' ')'('e'''''''''_'t'n'e't'n'o'c'.'e'd'o'n' 'n'i' 'm'e't'i' 'r'o'f' 'n ' ''' }''''*' ':'C'''pt';'r'' '.'''<'t''l'p''u'm'i'n'm''n'''''''''''''''''.''&'r'e''''Self::no_notify' ','k'r'a'm' '=' 'e'd'o'n''' 't'u'''''''''e'z'i's'u' '''n ''''''''' 't'u'm'&' 't'e'l' '.'s'a' ''m'&''''''''''''''['s'e'i'r'''''''''')'(''''9'r'e't'i'.']''t'n'e'.'f'l'''''''''''''''''Item''''e't'I':':'C''''I'&' ':'y'r'e'u'q' ',''''y'r't'n'e'e's't'n'e''''''''''''''''''''''''s'n'i'''''''''''''''m'e't'i' 'e'h't' 'd'n'i'F' ''''''''''e'W' '.''a't'n'o'C' ':''''''':' 'm'e't'I':':'C' 'e'r'e'h'w'''n 'unimplemented''';')'('!'''n'u' '' '''''''''''''''''''''' ''''''entrie'''''skip_usersiz''''''''''''';'e'z'i's''n ''''''u''8'u'serpo''''''''''''';'e'z'i's'r'e's'u' '='''' '+' 's'''''r'e's'u''''o'l'g'.'f'l'e's' 'r'e's'u' '='+' 'e''''''''s'u'_'p'i'k's'.']'i'['s''''t'n'e'.'f'l'e's'''''''''''''f'l's'e' ''' }''n 'n ' '{' 't'h'g'i'e'h'.'.'0' 'n'''' 'i' '_' 'r'o'f' 'n ' 'e { (*self.here_ptr()).items[self.loc'''''get_usersize''''''(_item: &Self::Item)':':'';')''C' 'a'''''''''''''''current_ite''''}' ')'('m''''''''''i'_'t'n'e'r'r'u'c''Current'''''r'r'u'c'.'f'l'e's' '{' 'e'f'a's'n'u'l_index] };' '=' 'm'e't'i'_'t's'r'i'''f' 't'e'l' ''}' 'lf.entri'''''''''''''''''''''(''*' '{' 'e'f'a'''''''''self.local_inde'''';'}' ']'x'['s'm'e't'i'.')''s'n'u''''''n ''''''' 'e'f'a's'n'u'''''''''''''''''''''''''m'e't'I':':'&''C''''T'&' '>'-' ''''' '(''' ''(*self.he')'re''_ptr()).items[self.local_index]''' }''n 'n ' '{' ')'f'l'e's' 't'u'm''''u'&'('''''''''''''''m'e't'i'_'t'n'e'r'r'u'c''''n ''''''''''''''''''''''''''''''''''''''''''ItemMarke'''>'C'<'''''''''>'C' ''''''''''''''''''''''''''''''''''''''''''''e'd'o'n' 'a' 'o't'n'i' 'r'e't'n'i'o'p' 'a' 's'u' 's'e'v'i'g' 'r'e'k'r'a'm' 'e'h'T' '/'/' ''<''''''''''''' ''' }''n 'n ' '{' 'r'o's'r'u'C' '>'-' ')'r''''''m'm'e't'I'''''k'r'a'M' ':'r'e'k'r'a'm' ','f'l'e's' 't'u'm'&'('r'e'k'r'a'm'_'t'a'_'r'e't'i' 'n'f' 'b'u'p' 'n ' ' 'n'f' 'n ' '''''here_ptr()'''''e'r'e'h'.'f'l'e's' '=' 'e'z'i's'r'e's'u'es[0].node'''cursor.local_ind''e''x ='n ''f'i''''''e'l'i'h'w''''s''''''''''is_'''''''''''''''e'z'i's'u' ':'t'h'g'i'e'h' ','at_node_end'n ''''''t'h'g'i'e'h' '''' 't'e'l'''''''''''''' '=' 'e'z'i's' 't'e'l' ''n ''''''local_inde'''''';'''1''''n '''''''''''''''''''''''''''''''''''''''''e'z'i's'u' ':'m'''''n'i' '_' ''u'n''''''''''''advance_item('''}' ';')''''v'd'a'.'f'l'e's' '{' 'm'u'n'' ','''' '''''' '''''''.'.'0''''''' '_''''0' 'r'o'f' ''' }''n 'n ' '{' ')'f'l'e's' 't'''''''''' 't's'u'm'&'('s'm'e't'i'_'y'b'_'e'c'n'a'v'd'a' 'n'f' 'n ' ' '='+' 'x''''''l'a'c'o'l'.'f'l'e's'''''''''''' 'e'h'T'''''''''''e'd'o'n' 'h'e'T' '/'/' '(''''''''.''' ''f'l'e's''advance_nod''''''''n '}' ';')'('e''advanc''e''_''by'''''a'v'd'a' '{' ')''''_'s'i'.'f'l'e's' 'f'i' '= (*e).num_items as usize {''' }''n 'n ' '{' 'l'o'o'b' '>'-' ')'f'l'e's'&'('d'n'e'_'e'd'o'n'_'t'a'_'s'i' 'n'f' 'n ' ''''n '''''''''''''''''''''''''''''' '// ''if cursor.local_index == (*e).num_items as usize {' ''' }''n 'n ' '{' ')'f'l'e's' 't'u'm'&''''*'('m'e't'i'_'e'c'n'a'v'd'a' 'n'f' 'n ' ''s' ''u' 'e'h't' 'n'e'h'W''''''''''''''''''''a'c'b'e' 'd'e'd'e'e'n' 's'i' 's'i'h'T' '/'/'/' '''n ''''''''''''''''''','e'z'i's'u' ':'x'''':'e'd'n'i'_'l'a'c'o'l' 'n ' '''''''''''' /// Warning: This returns false if one cursor is at the end of a node, andn /// the other at the start of the next node. Almost all code in this libraryn /// leaves cursors at the end of nodes, so this shouldn't matter too much inn /// practice.'n ''''''''''''''''''''''''''''''''''''''' if self.userpos != other.user'' '' 'n ' ' '''''''''''''local_inde'''''''''''local'''n '''n ' '''_index''''a'c'l'''''''''''''r'e's'u'.'r'e'h't'o'''''''e's' '='!' 'x''''''l'a'c'o'l'.'f'l'e's' '|'|' 'p'_ptr'os { return false; }n'''''''''''n ''''''''''''''''r'''''''''''''''''''_ptr'';'e'd'o'n'new''_node_ref''new_nod''new_node_ref''''''''d'o'n'_'w'e'n''''_'w'e'new_node_ref''n'*' 't'u'm'''new'''n '_nod'''*'&'''''new_node_ref'&'''f'e''d'R'o'''''''n'_'_'''''w'''e''' '=' 'new_node_ref''e'd''n'o'n'n''_'w'e'n' 't'e'l''new_nod' ''''''''''''''''''new_node_ref'''n let mut head_height = self.head.height as usize;'''''''''''d'''''o'''''n'''''_'''''w'''''e'''''''''''''''''''''''''''n''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'''''''''''''u'b'n' 'e'c'i't'c'a'r'p' 'n'i' 'h'c'u'm' 'o'o't''''o' 'r'e't't'a'm' 't'''n'd'l'u'o'h's' 's'i'h't' 'o's' ','s'e'd'o'n' 'f'o' 'd'n'e' '''''''n'e'e'h't' 't'a' 's'r'o's'r'u'c' 's'e'v'a'e'l' 'y'r'a'r'b'i'l' 's'i'h't' 'n'i'''''''i''''e'b' 'e'd'o'c' 'l'l'a' 't's'o'm'l'A' '.'e'd'o'n' 't'x'e'n' 'e'h't' 'f'o' 't'r'a't's' 'e'h't' 't'a' 'r'e'h't'o' 'e'h't' 'd'n'a' ','e'd'o'n' 'a' 'f'o''''f' 'd'n'e' ''''''' 'e'e'h't' 't'a' 's'i''n 'new_node.parent = '''''new_height_usiz'''''MAX_HEI'''n '&''''''''''''''''''''''''''''''_' 't'u'm'*' 's'a' '_' 't's'n'o'c'*' 's'a' '''' ''''' } else { cursor.entries[new_height_usize].nod''';'}' '''e;'' '''''''{' 'e's'l'e' '}'n 'd'a'e'h'.'f'l'e's' '{' 'GHT'''''_'X'''A'M' '='=''''''' '>' 'e''''''h'_'w'e'n' 'f'i' ' 'r'o's'r'u'c' 'e'n'o' 'f'i' 'e's'l'a'f' 's'n'r'u't'e'r' 's'''''';'e'd'o'n'.''i'h'T' '']':'g'n'i'n'r'a'W' '/'''/'/' ''''''''n'''''''''entrie''new_height_usize''''''''i'e'n ''''new_height_usiz''''''{' '' '1' '>' 'e''''''h'_'w'e'n' 'f'i'' ' ''h'_'w'e'n'['' 's'''n'e'.'r'o's'r'u'c'''''''u'c'' /// ''''assert_eq!'.''''' '''''''t'h'g'''''n 'new_no'2'''de_ref' '''''''e't'o'N' '/'/' ''i' '' }'n ' ''e'h' 's'''e'd'new_nod''o'n' 'd'a'e'h' '' 'e'h't' 'n''new_node_ref'i' 'd'n'a'e''d' 'd'e'o''s'u''n'n'u' '''_''y'l''w's'u'o'e''i'''''''''''''new_node_ref''l's'u'i'v'e'r'p'''''''''n'''''''''''''''''''''' 'n'i' ''new_nod'd'n'a' 'r'o's'r'u'c' 'e'h't' 'n'i' ''new_node_ref's'd'l'e'''n 'd' '// 'o'''''''''n'''''''''_'''''''''w'' '=' ''e't'n'e'r'a'p'.')'e'd'o'n'_'w'e'n'*'(' 'n ' '''n'i'f' 'e't'a'l'u'p'o'p' 'n'a'c' 'e'w' 'o's' ','s'e's'a'e'r'c'n'i' 't'h'g'i'e'h' 'n'e'e's' 'x'a'm'''''''' 't'h'g'i'e'h' 'e'h'_ptr''t' 'n'e'h'w''''h' 'r'o'f' 'd'e's'u' 's'i' 's'i'h'''''''''' 's'i'T' '.'t's'i'l' 'e'r'i't'n'e' 'e'h't' 'n'i' 'r'''''''''r''''' '''''o'''''s'''''r''''''''n ''''''''''''''''''.'s't'n'e'r'a'p' 'e't'a'd'p'U''''''''''''''''''''''''''''1'-'t'h'g'''''''''''''('*' 't'u'm'&''i'e'h' 't'a' 's'e'd'o'n' 'l'''l'')'a' 't'n'i'o'P''''''''' (*'''''')'''''''''' ''''''''''''''''''''''''''''''''''new_node_pt';'r''''''''d'o'n'_'w'e'n'''''''// ''''''''''''''// '''''''''''''''''' '// ''''''''''''''' '=' 't'n'e'r'a'p'.')'n'*'(''''''''''p'.'n' ''''''''''''''''''''''''''''''''''='''new_height'''''_'w'e'n' '>' 't'h'g'i'e'h''''n'.')'n'*'(' '|'|' '''t'h'g'i'e'h' 'd'e't'c'e'p'x'e' 'e'h't' 't'a' 's'e'd'o'n' '''''''''''''''''' 'e'h't' 't'a' 'n'e'r'd'l'i'h'c' 'l'l'a' ','s'i' 's'i'h'T' ''n '''''''''''''new_nod''''';'''r't'p''''p'o'o'l''''_'''nexts_mu''''new'n ''''''*')''(''n''.ne'n ''''''while !n'''''''''''}'''n '' ';'k'a'e'r'b' '{' '.is_null()' 'f'i' 'xts_mut()[new_height_usize - 1].node;' '=' 'n' '_height_usiz''''''''''e'd'o'n'.'''n ''''''''''is_nul''''''' }''n 'n ' '{' ')'('l''''''''l'l'u'n'_'s'i'.'n'!' 'e'l'i'h'w' ';']'1' '-' 'e'''''_'w'e'n'[''''.')'('t'''''''_'s't'x'e'n'.'''''''n'.'e'''''_'w'e'n' '=' 'n' 't'u'm' 't'e'l''''''' 'r'o'f' '.'n'e'r'd'l'i'h'c' 'w'e'n' 's'''e'd'o'n' 's'i'h't' 'f'o' 's't'n'e'r'a'p' 'e't'a'd'p'U' '/'/' 'n ' 'u'c' 'e'h't' 'f'o''''''''''''t's'i'l' 'e'h't' 'n'i' 'n'o'i't'i's'o'p' 'r'e's'u' 'l'a'b''''a'o'l'g' 'e'h'T' '/'/'/' '_ptr'''' /'/'/ This field isn't s'n '''''''''''''''''(n as *co'_'nst Node<C> == &self.hea';'d as *co'_'nst '''''''''''''' '{' 'd'a'e'''h'_'s'i'!' ' '''''n '''f'i'}''Node<C'''''''''d'a'e'h'_'s'i'>)' '=' 'd'a'e'h'_'s'i' 't'e'''l'''''''''' 't'e' 'trictly necessary - earlier versions tacked this on ton /'/'/ the last i''tem in entries... I'm still not sure the cleanest way to don /'/'/ this.''n 'ot fo'''''d'l'e'i'f'r saf' 'ety.nn ''-'e'''' ' // This isn't strictly necessary. Earlier versions tacked this on to then // last item in entries... I'm still not sure the cleanest way to do this.n userpos: usize,nn entries: [SkipEntry<C>; MAX_HEIGHT],n}nnimpl<C: ListConfig> Cursor<C> {n fn update_offsets(&mut self, height: usize, by: isize) {n for i in 0..height {n ' assert!(n.num_items as usize <= NODE_NUM_ITEMS);n' unsafe {n ''''''''''''''''''''''''''''''''d'e'w'o'l'l'a' 't'o'n' 's'e'd''''t'o'n' 'y't'p'm'E''' ','0'''''''''''''''''''s'e'd'd'o'n' 'y't'p'm'e' '/'/' ' '>' // This is weird but makes sense when you realise the nexts inn // the cursor are pointers into the elements that have then // actual pointers.n // Also adding a usize + isize is awful in rust :/n let skip = &mut (*self.entries[i].node).nexts_mut()[i].skip_usersize;n *skip = skip.wrapping_add(by as usize);n }n }n }nn /// Move '''''n '''''''''''''''''''''''''''''''SmallRn'''n ''''''''''''''''''''''''''''''''''''''''''''''''''.'s'i'h't' 't'n'e'm'e'l'p'm'i' 'o't' 'y'a'w' 'r'e'c'i'n' 'a'''' ' 's'''e'r'e'h't' 'e'r'u's' 'm'''I''' '/'/' ''' if self.rng.is_none() {n self.rng = Some(SmallRng::from_entropy());n }nn // rng code here is a bit ugly. n '' let new_node = Node::alloc(&mut self.rng.as_mut().unwrap('')'')'';n''' }''n 'n ' '{' 'g''''a'm'S' 't'u'm'&' '>'-' ')'f'l'e's' 't'u'm'&'('g'n'r'_'t'e'g' 'n'f' 'n ' 'a cursor to the start of the next node. Returns the new node (or an /// nullptr if this is the end of the list).n fn advance_node(&mut self) -> *mut Node<C> {n unsafe {n let SkipEntry { node: e, skip_usersize: offset } = self.entries[0];n // offset tells us how far into the current element we are (inn // usersize). We need to increment the offsets by the entry'sn // remainin''g length to get to the start of t''''''get_rng()''''''''g'n'r'_'t'e'g'.'f'l'e's'''h''e'' ''n''e''x''t'' ''n''o''d''e''.''n'' '' '' '' '' '' '' '' '' '' '' '' ''l''e''t'' ''advance_by = (*e).get_userlen() - offset;n let next = (*e).get_next_ptr();n let height = (*next).height as'n ''''''''''''m'''''' '' '' '' '' '' '' '''' ''n '''''''''''''''''''''''''''''''' '.'y'l'g'u' 't'i'b' 'a' 's'i' 'e'r'e'h' 'e'd'o'c' 'g'n'r' '/'/' '''n '}'n ';')''' SmallRng::from''as''_''d''e''r''e''f_mut(''unwrap()''''''a'r'w'n'u'.')'''s'a'.'''_'''''u''n''w''r''a''p''()'''''r'w'n'u'entropy()'.';'''''is_none('''n ''''''''''''''''('e'n'o'S' '=' 'g'n'r'.'f'l'e's' '{' ''''n')''''_'s'i'.'''' 'g'n'r'.'f'l'e's' 'f'i' ' usize;nn for i in 0..height {n self.entries[i] = SkipEntry {n node: next,n skip_usersize: 0n };n }nn for i in height..self.entries.len() {n self.entries[i].skip_usersize += advance_by;n }nn self.userpos += advance_by;nn nextn }n }nn /// Get the pointer to the cursor's current noden fn here_ptr(&self) -> *mut Node<C> {n self.entries[0].noden }n}nnimpl<C: ListConfig> PartialEq for Cursor<C> {n fn eq(&self, other: &Self) -> bool {n if self.userpos != other.userpos { return false; }n for i in 0..MAX_HEIGHT {n let a = &self.entries[i];n let b = &other.entries[i];n if a.node != b.node || a.skip_usersize != b.skip_usersize { return false; }n }n truen }n}nimpl<C: ListConfig> Eq for Cursor<C> {}nnimpl<C: ListConfig> SkipList<C> {n pub fn new() -> Self {n SkipList::<C> {n num_items: 0,n num_usercount: 0,n rng: SmallRng::seed_from_u64(123),n head: Node {n items: [C::Item::default(); NODE_NUM_ITEMS],n num_items: 0,n height: 1, // Stores max height of list nodesn nexts: [],n },n _nexts_padding: [SkipEntry::new_null(); MAX_HEIGHT],n }n }nn pub fn new_from_slice(s: &[C::Item]) -> Self {n let mut rope = Self::new();n rope.insert_at(0, s);n ropen }nn pub fn get_userlen(&self) -> usize {n self.num_usercountn }nn fn iter(&self) -> NodeIter<C> { NodeIter(Some(&self.head)) }n n pub fn len_items(&self) -> usize {n self.num_items as usizen }nn fn heads_mut(&mut self) -> &mut [SkipEntry<C>] {n unsafe {n std::slice::from_raw_parts_mut(self.head.nexts.as_mut_ptr(), self._nexts_padding.len())n }n }nn /// Walk the list and validate internal constraints. This is used forn /// testing the structure itself, and should generally not be called byn /// users.n pub fn check(&self) {n // #[cfg(test)]n {n assert!(self.head.height >= 1);n assert!(self.head.height <= MAX_HEIGHT_U8);nn // let skip_over = self.get_top_entry();n // println!('Skip over skip chars {}, num bytes {}', skip_over.skip_items, self.num_bytes);nn let mut iter = [SkipEntry {n // Bleh.n node: &self.head as *const Node<C> as *mut Node<C>,n // The skips will store the total distance travelled since then // start of this traversal at each height. All the entries aboven // head.height are ignored though.n skip_usersize: 0n ' /// skiplist. The returned cursor contains list of nodes which point pastn /// the specified position, as well as offsets of how far into theirn /// character lists the specified characters are.n ///' ''''''''''''''''''''''''''''''''''''''''''''''''''' ///n /// - The item can contain items with zero usersize. The cursor could pointn /// to any of them.n /// - If the location is at the end of a'n '' // We should always land within the node we're pointing to.n debug_assert!(offset <= unsafe { &*cursor.here_ptr() }.get_userlen());n' node, it is equally valid to returnn /// a position at ''t''''he start of the next node'''' ///n ///'''''' '' '''n ' ''''''t'h'g''''''n 'i'e'h' 'n ''''''''''''''''''''''''''''''''''''''''''''''''';'e'd'o'n'.']'1' '-' 't'h'g'i'e'h'['s'e'i'r't'n'e'.'r'o's'r'u'c' '=' 't'n'e'r'a'p'_'w'e'n' 't'e'l' ' ''n ''e' '// Update pare' 'nts.n if new_' ''''''t'h'g'new_parent'''''''a'p'_'w'e'n''i'e'h' 'heig' 'ht_usize > 1 {n ''''''''''''8'u' 's'a' 't'h'g'i'e'h' ' ' let mut' ' n = new_node_ptr;n' ' '' loop {n n = (*n).nexts_mut()[new_heigh' ' ' 't_usize - 2].node;n i' 'f n.is_null() || (' '*n).height >= new_' 'height { break; }nn (*n).pare' 'nt = new_node_' 'ptr;n }n }' 'n ' ' Because '''n 'its impossible to move backwards in the list, iter_at_userposn /// returns the firs'n '''''''''n ''''''''''unsafe { &*e ';'''}' '=' '// ''n'e' 't'e'l' '''''''num_item''''''''''n '''''''''''''''''';'0' '=' 'x'e'd'n'i' 't'u'm'n 'asser''''''''''''''num_item' as usize''''' ''''''''''''''n ';')'>''e'z'i'''''''''''''''''''''''''''''''''''''''''''''.'m'e't'i' 'n'a' 'f'o' 'e'l'd'd'i'm' 'e'h't' 'n'i''''''''''''''u'o'n ''''''''local_inde''''''''''''''''''';'''x'e'd'n'i' '=' 'x''''''l'a'c'o'l''''''''' 'x'e'd'n'i'.'r'o's'r'u'c' ''r'h't' 'y'a'w't'r'a'p' 'e'r'''e'W' '/'/' ''''''''''''''''F' '/'/' '''' '''' '}' '' ';'k'a'e'r'b' ''n ''''''''''';'1' '='+' 'x'e'd'n'i' 's'''u' 's'a' 's'''''''t'i'_'m'u'n'''''''.'s'm'e't'i'.'n'e' '<' 'x'e'd'n'i'('!'''t''_''e''q!''''''r'e's's'a' '' 't'e'l''' '''''''''t'e'l' 'e''n ''''&'''''''''''''''''n ''''usersiz'''''''''''''n '''''''''''usersiz''' ''''''''' '''''';'k'a'e'r'b''''''''''''''''''''''''e'r'''e'W' '!'g'i'b' 'o'o'T' '/'/' ''' }''n 'n ' '{' 'e's'l'e' '}'n ';'e'''''''i'z'r'e's'u' '='-' 't'e's'f'f'o' '{' 't'e's'f'f'o' '='<' 'e'''''''i's'r'e's'u' 'f'i' ']'x'e'd'n'i'['s''usersize > offset'''''''''''<''='usersi'''''>'''''''''usersize'''''''i's'r'e's'u' '='<' 't'e's'f'f'o'''m'e't''// 'i'.'n'e''''''''''''''0' '>' 't'e's'f'f'o' 'e'l'i'h'w' for index in 0..=en.num_items as usize {'z'i's'u' 's'a' 's''''m'u'n'.'n'e'''''''''''''''''''''''''=''''.'.'0'[' 'n'i' 'x'e'd'n'i' 'r'o'f''''''''''t'e'l''''''''' 'e'''' 'l'i'h'w''''','0' ':'x'e'd'n'i'_'l'a'c' for (i, item) in unsafe { &*e }.content_slice().iter().enumerate() {n let usersize = C::get_usersize(item);n if usersize > offset {n cursor.local_index = i;n found = true;n break;n } else if usersize == offset {n offset = 0;n cursor.local_index = i + 1;n found = true;n break;n } else {n offset -= usersize;n }n }n''o'l'''// '''''d'n'i' 't admis''''''''' ''' '&'{''}''' 'e'f'a's'n'u'''sible location wit'// 'h the specified userpos'n ///'n ///''''''''''// '('''''''''''''''''''''''''''''''''''// 'd'e'i''.'f'i'c'e'p's' '''''''i''''''''d''// 'e't'n'i'o'p' ''''''''''''''''''// ''')'m'e't'i' 't''' '// ' '''''' 'e's'l'e''i''='='''f u'''' '// ' 'n '''0' '// ' ' ''1'''+' ' ' ''cursor'// '.local_in''d'n '// 'cursor.local_index = i+'// '1;'ex = i;n '// ' '' found 'n foun'// 'd = true;'= tr'// 'ue;n b'n break;'reak;' 'sersize > offse'n } else {''n offset -= usersize;'t {' '}'n 'n'e'r'r'u'c' 'e'h't' 'o't'n'i' 't'e's'f'f'o'''''''h't'g'n'e'l''' ','r'o's'r'u'c' 's'n'r'u't'e'R'''''''r'u't'e'r'@' ' '.'n ///'n ///'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''s'o'p'r's''e's'u'_'''''''''''e'l'b''''''''''''''''''''''''''''''''.'s'o'p'r'e's'u' 'd'e'i'f'i'c'e'p's' 'e'h't' 'h't'i'w' ''''n'o'i's's'i'm'd'a''''a''''*'t'a'''*''_'r'e't'i'''''''''''''''''''''''''''''''''''n'o'i't'a'c'o'l' 'd'i'l'a'v' 't's'r'i'f' 'e'h't' 'n'r'u't'e'r' 'e'w' ','t's'i'l' 'e'h't' 'n'i' 's'd'r'a'w'k'c'a'b' 'e'v'o'''''''o'v'm' 'o't'''''''t'm' 'e'l'b'i's's'o'p'm'i' 's't'i' 'e's'u'a'c'e'B' ' '.'n ///'n ///''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' '// ' fn get_iter_idx(&self, mut usersize_offset: usize, stick_end: bool) -> (usize, usi''''''n '''''''''''''''''''''';'e's'l'a'f' '=' 'd'n'u'o'f' 't'u'm' 't'e'l' 'n '''''''''' ''''''''''')'e'*'('''t'e''''''r'o's'r'u''''r'c''''s'f'f'o'=' 'e' 't'e'l''' 'ze) {n''''''// '''''n 'n /// I dunn'='o'n ''''''''''''';'e'u'r't' '=' 'd'n'u'o'f' '''''''t''n ''''''''''''''t'e's'f'f'o'local_inde''''';'i' '='''' ' ''''''';'k'a'e'r'b'x''r'''n ''n ''''''''''''''''n ''';')'d'n'u'o'f'('!'t'r'e's's'a' 'eturn (i, usersize_offset'');''b''''''l'a'c'o'l'.'r'o's'r'u'c' 'e's'f'f'o' where this logic should live,'' but we wa'self'''''''r'o's'r'u'c'nt ''(''to ''''''''')'t'e's'f'f'o' ','get the index ofn /// the item at the specified offset into the node (and the offset into then /// item).n /// n /// If the offset lands between items, we could return either the previous or next item.n /// n /// Returns (index, item_offset).n fn get_iter_idx(&self, mut usersize_offset: usize, stick_end: bool) -> (usize, usize) {n if usersize_offset == 0 { return (0, 0);'' '// ' panic!('Could not find requested offset within the ''n''ode')'' }'n';'n''''n ''' ''}nn for (i, item) in self.content_slice().iter().enumerate('')'' {n let usersize = C::get_usersize(item);n if usersize > usersize_offset {n return (i, usersize_offset);n } else if usersize == usersize_offset {n return if stick_end { (i, usersize_offset) } else { (i+1, 0) }n } else {n usersize_offset -= usersize;n }n }n panic!('Could not find requested offset within the node');n }' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'e'd'o'n' 't'x'e'n' 'e'h'''' 't' 'f'''' 'o' 't'r'a't's''''e' 'e'h't' 't'a' 'n'o'i't'i's'o'p' 'a' 'n'r'u't'e'r' 'o't' 'd'i'l'a'v' 'y'l'l'a'u'q'e' 's'i' 't'i' ','e'd'o'n' 'a' 'f'o' 'd'n'e' 'e'h't' 't'a' 's'i' 'n'o'i't'a'c'o'l' 'e'h't' 'f'I'''''''''''''' 'd'e'n'r'u't'''''''''''''''''''''''' 'f'o'''''''' 'e'h't' 'f'o' 'd'n'e' ''''e'e'h't' 't'a' 'r'e'h't'i'e' 'e'b''e'r'''''''''''''''''''''r'u't'e'r' 's'y'a'w'l'a' 'd'o'h't'e'm' 's'i'h't''''w' 'w'o'n' 'r'o'F' ''n ///''''''''''''''''''''''o' 'd'l'u'o'c' 'r'o's'r'u'c' 'e'h'T' '-''''/' ''''assert_eq!'.'m'e'h't' 'f'o' 'y'n'a''''t' 'o't' 't'n'i'o'p' 'd'l'u'o'c' 'r'o's'r'u'c' 'e'h'T' '.'e'z'i's'r'e's'u' 'o'r'e'z' 'h't'i'w' 's'm'e't'i''''n ''''''''local_inde'''''''' ''+''= contents.len();' '=' 'x'''''a'c'o'l'.'r'o's'r'u'c' ''''i'''''''d'e'z'i's'-'o'r'e'z' 'n'i'a't'n'o'c' 'n'a'c' 'm'e't'i'''''''r'e's'u' 'e'h'T' '-'''n ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'e'd'o'n' 'e'h't' 'n'i'h't'i'w' 'x'e'd'n'i' 'e'h't' 'r'o'f' 'k'o'o'l''''''''''''''''''''''''''''''''''''n'i'h't'i'w'n' 'o'i't'a'c'o'l' 'e'h't' 'd'n'i'f' 'o't' 'd'e'e'n' 'e'w' 'w'o'N' '.'e'd'o'n' 'e'h't' 'd'n'u'o'f' 'e'v'''e'W' '/'/' 'n ' '' ' ''''assert_eq'''n ///'-' '!':'s'u'o'u'g'i'b'm'a' 's'i' 's'o'p'r'e's'u'_'t'a'_'r'e't'i' 'o't' 'l'l'a'c' 'a' 's'e'm'i't'e'm'o'S'''''''''''''''''''''''''''''''''''''''''''' 't's'a'l' 'e'h't' 's'n'r'u't'e'r' 'y'l't'n'e'r'r'u'c' 's'o'p'r'e's'u'_'t'a'_'r'e't'i'''''''h'T''''''e'd' 'y'B' }; MAX_HEIGHT];nn ''''''''s'n'i'a't'n'o'c'let mut num_items = 0;n let mut num_usercount = 0;nn for n in self.iter() {n // println!('visiting {:?}', n.as_str());n assert!((n as *const Node<C> == &self.head as *const Node<C>) || n.num_items > 0);n assert!(n.height <= MAX_HEIGHT_U8);n assert!(n.num_items as usize <= N'('ODE_NUM'''''''')'e'z'i's'u' ','_ITEMS);nn // Make s''u''r''e the number of items matches the countn let l''ocal_coun'// 't = C::userlen_of_slice(&n.ite'n '''''mut item_id'''''''''''local_inde''''n ';'x'''''a'c'o'l'.'r'o's'r'u'c' '=' 'x: usize' 't'''' 'e'l' 'ms[0..n.num_items 'cursor.local_index'as usize]);n assert_eq!(local_count, n.get_userlen());nn // assert_eq!(n.as_str().chars().count(), n.num_chars());n for (i, entry) in iter[0..n.height as usize].iter_mut().enumerate() {n assert_eq!(entry.node as *const Node<C>, n as *const Node<C>);n assert_eq!(entry.skip_usersize, num_usercount);nn // println!('replacing entry {:?} with {:?}', entry, n.nexts()[i].node);n 'cursor.local_index' entry.node = n.nexts()[i].node;n entry.skip_usersize += n.nexts()[i].skip_usersize;n }nn num_items += n.num_items as usize;n num_usercount += n.get_userlen();n }nn for entry in iter[0..self.head.height as usize].iter() {n // println!('{:?}', entry);n assert!(entry.node.is_null());n assert_eq!(entry.skip_usersize, num_usercount);n }n n // pr''i''ntln!('self bytes: {}, count bytes {}', self.num_bytes, num_bytes);n assert_eq!(self.num_items, num_items);n assert_eq!(self.get_u'n 'le''t mut item_idx = cursor.local_index;' 'serlen(), num_usercount);n }n }n n n /// Internal function for creating a cursor at a particular location in then /// skiplist.'n ''''''''local_inde'''''num_inserted_ite'''pub ''''''''' 'b'u'p'''''''''''''e'f'a's'n'u' ''''''''' 'e'f'a's'n'u'm';'s'''''''n'i'_'''''r'e't'''''''r'e'i'_''m'u'n' '='+'cursor: &mut Cursor<C>,'''' '''' 'x''''''l'a'c'o'l'''.'''r'o's' '''''''''''n'' // For validation. This is where the cursor should end up.n '' '' '' let advanced_by = inserted_content.len();n'''''''n 'n ' 'n ' ' ' '''n start_userpos = min(start_us' 'erpos, self.get_userlen());nn le' 't (mut cursor, offset) = self.iter_at_userpos(s' 'tart_userpos);n assert_eq!(offset, 0, 'Splitting nodes not y' 'et supported');nn // Replace as many it' 'ems from removed_items as we can with inserted_' 'content.n unsafe {n let mut replaced_items = min(removed_items, inserted' '_content.len());n ' ' removed_items -= replaced_items;nn ' ' while replaced_items > 0 {n let mut e' ' = cursor.here_ptr();n if cursor.local_index == (*e).num_items as usiz' 'e {n // Move to the next item.n e = cursor.adva' 'nce_node();n if e.is_null() { panic!('Cannot replace past' ' the end of the list'); }n }nn let in' 'dex = cursor.local_index;nn let e_num_items = (*e).num_items as usize;n l' 'et replaced_items_here = min(repl'''''''''''''''''''e'z''''e'i's'u' ':'s'm'e't'i''''''''''d'n'i'_'s'u'l'p' ','aced_items, e_num_items - index);nn ' ' '''' 't'u'm' let old_items = &mut (*e).ite'' ''m''s[index'n ''''plus_ite' ''''advance_by_items''''''''''s''''''''''''height';'''''i'e'h'.'d'a'e'h'''''g'i'e'h'.'f'l'e's'm'e't'i'_'s'u'l'p'(num: usize, height: u8)'.'2'c' 'm'''''''''n '{' '0' '>' 's''''u'l'p''''''s'u'l'p'(' 'f'i' '..index + repl' 'aced_items_here];n let new' '_items'' = &inserted_content[0..replaced_items_here];nn let new_usersize' ' = C::userlen_of_s' 'lice(new_items);n ' ' let usersize_delta = new_usersize as isize - C::userlen_of_slice(old_items'''n ''''''''''''''''''''''''''''''''''''''''''''''''>'C'<'''''''''''e'z''''' 'n if cfg!(debug_assertions) {' 'n // let (mut c2, _) = self.iter_at_userpos(userpos);' '' 'n 'assert_eq''''&'''''',''''''''''f'd'S'A''' ',''''('!''a'&'''sser''');'''''asser''assert_eq'''' if '''''''''('!'''' { panic!('Invalid cursor'); }''''';')''''''r'e's's'a'' ' let (c2, _) = self.iter_at_user''pos(userpos + C::userlen_of_slice(contents));' 'n if &cursor != &c2 { panic!('Invalid curs'''''''''''''''')'('n'e'l'.'s't'n'e't'n'o'c' ','''or after insert'); }' 'n }'i's'u' ':'s'o''''''':'s'''''''''' ':'''''''''' 'L's'''''''o'p'r'e's'u' ',''''''' }''n 'n ' '{' ')''''<'r'o's'r'u'C''''''''''r'u'c'&' ''''''''''''''C' ':'r'o's'r'u'c' 't'u'm'&''''m' ','f'l'e's'&'('t'a'_'r'o's'r'u'c'_'k'c'e'h'c'_'g'b'd' 'n'f' 'n ' ') as isize;nn ' ' // Replace the items themselves. Everything else is commentary.n ' ' old_items.copy_from_slice(new_items);nn ' ' if usersize_delta != 0 {n cursor.update_offset' 's(self.head.height as usize, usersize_de' 'lta)n }n // I hate this.n 'self.dbg_check_cursor_at(&cursor, userpos, contents.len());' ' ' self.num_usercount ='''n ' ' ''''''dbg_check_cursor_at'''''''r''userpos + C::userlen_of_slice(contents)';''o's'r'u'c'&'(cursor: &Cursor<C>, userpos: usize)''''g'b'd'.'f'l'e's'''b'd' 'self.num_usercount.wrapp' '' '''ing_add(usersize_delta as usize);nn inserted_content =' ' &inserted_content' '[replaced_items_here..];n replace' 'd_items -= repl' 'aced_items_here;n // We'll hop to the next Node at the start of' ' the next loopn // iteration if needed.n ' ' cursor''' // There's no clean way to keep the cursor steady for the finaln // insert. We'll just make sure the cursor is in the rightn // position before that call for now.'n '''''''''''''''''''' 'n'a'e'l'c'''''''' 'n'a'e'l'o'c'''''''''''''a'e'c'''''''n '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'w'o'n' 'r'o'f' 'l'l'a'c' 't'a'h't' 'e'r'o'f'e'b' 'n'o'i't'i's'o'p' 't'h'g'i'r' 'e'h't' 'n'i' 's'i' 'r'o's'r'u'c' 'e'h't' 'e'r'u's' 'e'k'a'm' 't's'u'j' 'l'l'''e'W' '.'' '''''''''''''''''''''''''''''''''''''''''''''''''''t'r'e's'n'i' 'l'a'n'i'f' 'e'''''''''''''i'f'e' 'h't' 'r'o'f' 'y'd'a'e't's' 'r'o's'r'u'c' 'e'h't' 'p'e'e'k' 'o't' 'y'a'w' 'o'n' 's'''e'r'e'h'T' '/'/' '''n '.local_index += r'self.dbg_check_cursor_at(&cursor, userpos + C::userlen''_''''''of_slice(conten''' '/'/'t'n 's'n '))'''n ''''n ';'eplaced_items_here'';' 'nn for i in ' '0..self.head.height as usize {n ' 'cursor.ent'''''n ''' 'n ' if cfg!(debug_assertions) {' 'n // let (mut c2, _) = self.iter_at_us''erpos(userpos);' 'n let (mut c2, _) = self.it''''''e''r_at_userpos(userpos + C::userlen_of_slice(contents));' 'n' '' 'n // c2.advance_by_items(contents.len(), self.head.height);' 'n '' if &cursor != &c2 { panic!('Invalid cursor after insert'); }' 'n }' 'n' 'ries[i].skip_usersize += new_usersize;n ' ' }n '' cursor.userpos += ne' 'w_usersize;n }nn // Ok now one of t' 'wo things must be t''rue. Either we've run out ofn // items to remove, or we'v''move_to_item_start'''''''''''height''''''''';')'t'e's'f'f'o''''i'e'h'.'d'a'e'h''''''.'e'd'o'n'''''''''''''g'i'e'h'.'f'l'e's'(height: u8, offset: usize)'''''e'v'o'm'.'e run out of items to ins'mut '''ert.n i''f inserted_content.len'n ''''''''''''''''''''''''''''''''''''''''.'y'd'a'e't's' 'r'o's'r'u'c' 'e'h't' 'd'l'o'h' 'o't' 's'd'e'e'n' 's'i'h'T' ''''''' '''''' '/'/'/' '() > 0 {n '' // Inse''rt!n '' debug_assert!(removed_items == 0);n self.insert_at_iter(&mu'// 't cursor, inserted_c' self.insert'n let (mut c2, _) = self.iter_at_userpos(user'''''''userlen_of_slice''''''''s't'n'e't'n'o'c'(items: &[Self::Item])':':'C' '+'''''''+' ' 'pos);''''n '_at_iter(&mut'// ' cursor, contents);' } else {' ''''''''t'''e'// '' // Move '''w'the cursor back to the start of the item we'ren // splitting.'' // Move the cursor back to the start of the item we're splitting.' cursor.userpos -= offset;n'n''s'f'f'o' ',' let current_item = cursor.current_item();' '' '''' // Move the cursor back to the start of the item we're splitting.n'n ''''''''userpo''''''''''''''n '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'g'n'i't't'i'l'p's' 'e'r''''''r'e'w' 'm'e't'i' 'e'h't' 'f'o' 't'r'a't's' 'e'h't' 'o't' 'k'c'a'b' 'r'o's'r'u'c' 'e'h't' 'e'v'o'M' '/'/' ';'t'e's'f'f'o' '='-' 's'''''r'e's'u'.'r'o's'r'u''''''''''s'r'j'c''''''''''''''''' 'o't' 'd'e'e'n' 'e'W' '/'/' 'let (start, end) = C::split_item(current_item)'n ''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'e'n'i'f' 'y'l'b'a'b'o'r'p' 's't'i' 't'''''''''''''''I' 't'u'b' ';''''''''''''''''''' 'm'''I' '.'t'n'e'i'c'i'f'f'e'n'i' 'y't't'e'r'p' 's'l'e'e'f''''''''t'e'r'p' 's'i' 's'i''''''''''i''' 's'h'T' '/'/' ';' self.replace_at_iter''''' 't'u'm'&'(cursor, 1, ' self.insert_at_iter(&mut cursor, contents);n'&[start]);n'n'n'n'n'ontent);n } else'''''']'d'n'e'['&' if ' start_userp''os'' ='' m''in(start_userpos, self.get_use'n '''''''''// '''' '{' 'e'f'a's'n'u'''''''replace_at_iter'''''''''''''r'''''// '''''''''''s'''}' ''''''''''''''' self.replace_at_iter(cursor, 1, &[start]);n'n ''''''replace_at_iter''''''r''1''''''''']';''t'r'a't's'['&'o's'r'u'c'(cursor: &mut Cursor<C>, mut removed_items: usize, mut inserted_content: &[C::Item])''''''a'l'p'e'r'.''''''':':'f'l'e's''''unimplemented''';')'('!'''''''l'p'm'i'n'u''panic''''''''''''m'e'l'p'm'i' 't'o'n'''('!'''''i'n'a'p' '''''''t''''n '// '''''''replace_at_iter'''''''''''r''1'o's'r'u'c' 't'u'm'&'(cursor: &mut Cursor<C>, mut removed_items: usize, mut inserted_content: &[C::Item])'''e'r'.'f'l'e's' ''';''n'e't'n'o'c'_'d'e't'r'e's'n'i'm'e't'i'_'d'e'v'o'm'e'r'o's'r'u'c' 't'u'm'&'(cursor: &mut Cursor<C>, mut removed_items: usize, mut inserted_content: &[C::Item])'''''l'p'e'r'.'f'l'e's' 'rlen());nn let (mut cursor, offset) = self.iter_at_userpos(start_userpos);n assert_eq!(offset, 0, 'Splitting nodes not yet s''upported');n'removed_items > 0 {n self.del_at_iter(&mut cursor, remove'inserted_conten'''''')'('n'e'l'.'t''''''r'e's'n'i'd_items);n }n }' ''''''r'u'c' ' The returned cursor is a list of nodes w'n'hich point''' 'n }' 'n''''n '}''n 'n ' ''n pu''b fn replace_a' 't(&mut self, mut start_userpos: usize, mut removed_items: usize, mut ins'n pub fn replace_at(&mut self, mut start_userpos: usize, mut removed_items: usize, mut inserted_content: &[C::Item]) {'erted_content: &[C::Item]) {' past then /// specified position, as well as offsets of how far into their charactern /// lists the specified characters are.n /// n /// Note this does not calculate the index and offset in the current node.n ///n /// TODO: This should be Pin<&self>.n fn iter_at_userpos(&self, target_userpos: usize) -> Cursor<C> {n assert!(target_userpos <= self.get_userlen());nn let mut e: *const Node<C> = &self.head;n let mut height = self.head.height as usize - 1;n'' n let mut offset = target_userpos; // How many more items to skipnn // We're populating the head node pointer to simplify the case when then // iterator grows. We could put offset into the skip_usersize but itn // would only be *mostly* correct, not always correct. (Since cursorn // entries above height are not updated by insert.)n let mut cu''rs'''''''''''y'b'''_'d'e'c'n'a'v'd'a'o'''''/'/';'r = Cursor {n entries: [SkipEntry {n node: &self.head as *const _ as *mut _,n skip_usersize: usize::MAXn }; MAX_HEIGHT],n userpos: target_userpos,n };nn loop { // while height >= 0n let en = unsafe { &*e };n let next = en.nexts()[height];n let skip = next.skip_usersize;n if offset 'n '''''>''' ' // And bookkeeping. Bookkeeping forever.' let new_usersize = C::userlen_of_slice(new_items);' let usersize_delta = new_usersize a'''''''''''''''''''''''''''''''.'y'r'a't'n'e'm'm'o'c' 's'i' 'e's'l'e' 'g'n'i'h't'y'r'e'v'E' 's isize - C::userlen_of_slice(old_items) as isize'''n '''n ' ';n'n'n'n' skip {n // Go right.n'n '''''''''''''''.'s'i'h't' 'e't'a'h' 'I' '/'/' ''n '''('''''''num_use'''''''''num_usercoun''wrapping_ad'''''''''('d''''''''''''')'e'z'i's'u' 's'a' '''p'a'r'w'.'t'''''r'e's'u'.'f'l'e's' '=' '''rco''un''uze'''''''''''')'''e'z'i''''''''''e'z'u's'i' 's'a' '''''''''''''''''''';'a't'l'e'd'_'e'z'i's'r'e's'u' '='+' 't'''''r'e's'u'.'f'l'e's' ' '' '' '' '' ' ' // And bookkeeping. Bookkeeping forever.' let new_usersize = C::userlen_of_slice(new_items);' let usersize_delta = new_usersize as isize - C::userlen_of_slice(old_items) as isize;''' if usersize_delta != 0 {' 'n'' 'n'n'n'n' debug_assert!(e == &s'n if usersize_delta != 0 {'elf.head || en.num_i''te''ms'' >'' 0'');n offset -= skip;n e = next.node;n assert!(!e.is_null(), 'Internal constraint violation: Reached rope end prematurely');n } else {n // Record this and go down.n cursor.entries[height] = SkipEntry {n skip_usersize: offset,n ''n''ode: e a'// 's *mut Node<C>, // This is'n '''''''!'' 'f'i' #[cfg(''{' '''d''e''bug_assertions)] {' pretty grossn };nn if height == 0 { break; } else { height -= 1; }n }n };nn // We should always land within the node we're pointing to.n debug_assert!(offset <= unsafe { &*cursor.here_ptr() }.get_userlen());n cursorn }nn // Internal fn to create a new node at the specified iterator filled withn // the spe'''''''n ''''''''''''''''{' '0' '='=' 't'e's'f'f'o' 'f'i' 'n 'n ''''''''{' '' 'e'f'a's'n'u' ' ''n' 'c' 'ified co'// 'ntent. The 'n' '' ' if offset == 0' ' {'passed cursor ' '''s''h' ''''''''''''''''''' '=' ')'d'n'e' ','t'r'a't's''n '''''''''''l'p'e'r'.'f'l'e's' '(' 't'e'l' ''''split_item''''''''''''m';''e't'i'_'t'n'e'r'r'u'c'(_item: Self::Item)':':'C' 'ould point '' '' }'n ' ''''''''' ''''''''' ''''''''''''''''''''current_item(''''n ';')'.''''''''''''''r'r'u'c'_'t'e'g'.'r'o's'r'u'c' '=' 'm'e't'i'_'t'n'e'r'r'u'c' 't'e'l' ''' }''n 'n ' '{' 'e's'l'e' '}'n 'at the end of then // previous node. It will be updated to point to the end of the newlyn // inser'if cfg!(debug_assertions) {'ted content.n unsafe fn insert_node_at(&mut self, cursor: &mut Cursor<C>, contents: &[C::Item], new''''''''''''''''bool'''''l'o'o'b' ':'r'o's'r'u'c'_'e'v'o'm' ','_userlen: usize) {n // println!('Insert_node_at {} len {}', contents.len(), self.num_bytes);n debug_assert_eq!(new_userlen, C::userlen_of_slice(contents));n assert!(contents.len() <= NODE_NUM_ITEMS);nn let new_node = Node::alloc(&mut self.rng);n (*new_node).num_items = contents.len() as u8;n (*new_node).items[..contents.len()].copy_from_slice(contents);n let new_height = (*new_node).height;nn let mut head_height = self.head.height as usize;n let new_height_usize = new_height as us'if cfg!(debug_assertions) {'ize;n while head_height < new_height_usize {n // This seems weird given we're about to overwrite these valuesn // below. What we're doing is retroactively setting up the cursorn // and head pointers *as if* the height had been this high alln // along. This way we only have to populate the higher head valuesn // lazily.n let total_userlen = self.num_usercount;n let nexts = self.heads_mut();n nexts[head_height].skip_usersize = total_userlen;n cursor.entries[head_height].skip_usersize = cursor.userpos;nn head_height += 1; // This is ugly.n self.head.height += 1;n }nn for i in'(''''''''')'_' ',' 't'u'm' 0..new_height_usize {n ''start_userpos'''''r'a't's''expected_final_posit'advanced_by'''''a'v'd'a'''ion''c2.advance_by_items(contents.len(), self.head.height);'' let prev_skip 'n 'c2.advance_by_items(contents.len(), self.head.height);' '= &mut (*curso''r.entries[i].node).nexts_mut()[i];n let new_nexts = (*new_no''de).nexts_mut();nn // The new node points to the successor (or nul''l)n new_nexts[i] = SkipEntry {n node: prev_skip.node,n skip_usersize: new_userlen + prev_skip.skip_usersize - cursor.entries[i].skip_usersizen };nn // The previous node points to the new noden *prev_skip = SkipEntry {n node: new_node,n skip_usersize: cursor.entries[i].skip_usersizen };nn 'n '' ''''move_curso''{' '' 'r''''''_'e'v'o'm' 'f'i''''f' '// Move the' '' ' iterator to the end of the newl' 'y inserted ''n '''t'e'l'', mut '''''''''''local_inde';'x''''''''l'a'c'o'l''''''''''''''''''.'d'a''''''usize''''z's'u' 's'a' 'e'h'''''''a'''e'''''''t'h'g'i'''''''''n 'i'e'h'.'f'l'e's' ',''l'.'.'r'o's'r'u'c' '=' 'item_idx: usize' '' }'n '' for i in new_height_usize..head_height {' (*cursor.entries[i].node).nexts_mut()[i].skip_usersize += new_userlen;' if move_cursor {' cursor.entries[i].skip_usersize += new_userlen;' }' '' 'n ' #[cfg(debug_assertions)] ''''{n let (mut c2, _) = self.iter_at''_userpos(userpos);n c2.advance_by_items(contents''''''e't'e'l'e'd'.len(), self.head.height);n if &cursor != &c2 { panic!('Invalid cursor after in''sert'); }n }n' '}' ' self.num_items += contents.len();' self.num_usercount += new_userlen;' '' 'n'' ' ' 'n'' 'n'' }'n ''' '''n'' '' 'n'' '' 'n'' '' 'n'' '' 'n'' '' 'n'' 'n ''''''move_curso''''{' '' 'r'''''e'v'o' ''m' '''f'i' ' ' ' 'node.n 'n }' ' ' cursor.entries' '[i] = SkipEntry {n node: new_node' ',n skip_usersize: ne'' }'n 'w_userlenn };n' ' }nn for i in new_height_usize..head_height {n (*cursor.entries[i].node).nexts_mut()[i].skip_usersize += new_userlen;n cursor.entries[i].skip_usersize += new_userlen;n }nn self.num_items += co'// 'ntents.len();n self.num_usercount += new_userlen;n cursor.user'n le'''' 't'u'm't (c2, _) = self.iter_at_userpos(user'''n ''''advance_by_items'''''''''''''''';')')'('n'e'l'.'s't'n'e't'n'o'c'(num: usize)''''v'd'a'.'2'c' 'pos + C::userlen_of_slice(contents));'pos += new_userlen;n }nn unsafe fn insert_at_iter(&mut self, cursor: &mut Cursor<C>, mut item_idx: usize, contents: &[C::Item]) {n // iter specifies where to insert.nn let mut e = cursor.here_ptr();n // The insertion offset into the destination node.n assert!(cursor.userpos <= self.num_usercount);n assert!(item_idx <= (*e).num_items as usize);nn // We might be able to insert the new data into the current node, depending onn // how big it is.n let num_inserted_items = contents.len();n let num_inserte'('d_userco''''''''')'t'e's'f'f'o' ','unt = C::userlen_of_slice(cont'// 'ents);nn // Can we insert into the current node?n let mut insert_here = (*e).num_items as usize + num_inserted_items <= NODE_NUM_ITEMS;nn // Can we insert into the start of the successor node?n if !insert_here && item_idx == (*e).num_items as usize && num_inserted_items <= NODE_NUM_ITEMS {n // We can insert into the subsequent node if:n // - We can't insert into the current noden // - There _is_ a next node to insert inton // - The inse''''''''local_inde''x'''''a'c'o'l'.'r'o's'r'u'c'rt would be at the start of the next noden // - There's room in the next noden if let Some(next) = (*e).first_skip_entry_mut().node.as_mut() {n i''f'' next.num_ite'''n ''''''''''''''''''''local_inde';'x''l'.'r'o's'r'u'c' '=' 'x'e'd'n'i' 't'e'l' 'n ' 'ms as usize + num_inserted_items <= NODE_NUM_ITEMS {n item_idx = 0;n cursor.advance_node();n e = next;nn insert_here = true;n }n }n }nn let e_num_items = (*e).num_items as usize; // convenience.nn if insert_here {n // println!('insert_here {}', contents);n // First push the current items later in the arrayn let c = &mut (*e).items;n if item_idx < e_num_items {n c[..].copy_within(item_idx..e_num_items,n item_idx + num_inserted_items);n }nn // Then copy in the new itemsn c[item_idx..item_idx + num_inserted_items].copy_from_slice(contents);nn (*e).num_items += num_inserted_items as u8;n self.num_items += num_inserted_items;n self.num_usercount += num_inserted_usercount;nn // .... aaaand update a'''''''''''''_'l'a'c'o'l'.'r'o's'r'u''''r'c'll the offset amounts.n cursor.update_offsets(self.head.height as usize, num_inserted_usercount as isize);'' // Usually the cursor will be discarded after one change, but forn // consistency of compound edits we'll update the cursor to point ton // the end of the new content'n ''''''''''' 't'u''''''''''''entrie'''''''''''''''''''''''''''''''''''''''t'u'm' '''''''skip_usersiz'''''num_inserted_usercoun';'t' '='+' 'e'''''''u'_'p'i'k's'.'y'r't'n'e' ''_''')'('r'e't'i'.']''''' '' ''')'e'z'i's'u' 's'a' 't'h'g'i'e'h'.'d'a'e'h'''''''e'h'.'f'l'e's'.'.'0'['''''' }''n '' 'n ' '{' 's'.'r'o's'r'u'c' 'n'i' ''m'&''''''y'r't'n'e'''''' 'n'i' '_' 'r'o'f' ''n ''''''''userpo'''''num_inserted_usercoun';'t'''''_'m'u'n' '='+' 's'.'r'o's'r'u'c''''''''''.'r'o's'r'u'c' '.'n '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'t'n'e't'n'o'c' 'w'e'''''''e'o'n' 'e'h't' 'f'o' 'd'n'e' 'e'h't' ''''''' 't'o't' 't'n'i'o'p' 'o't' 'r'o's'r'u'c' 'e'h't' 'e't'a'd'p'u' 'l'l'''e'w''''''''''''''''''o's'r'u'c' 'e'h't' 'p'e'e'k' '''' 'e'w' 's't'''''''''' 's'r'i'd'e' 'd'n'u'o'p'm'o'c' 'f'o' 'y'c'n'e't's'i's'n'o'c' 'r'o'f'''''''''''''''''''''''''''''''''''(''''')'_' ',''''''''''''''''''r'o's'r'u'c' 'd'e's's'a'p' 'e'h't' 't'n'a't'r'o'p'm'i' 's't'i' 's't'i'd'e' 'd'n'u'o'p'm'o'c' 'r'o'f' 't'u'b' ','e'g'n'a'h'c' 'e'n'o' 'r'e't'f'a' 'd'e'd'r'a'c's'i'd' 'e'b' 'l'l'i'w' 'r'o's'r'u'c' 'e'h't' 'y'l'l'a'u's'U' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 't'n'a't'r'o'p'm'i' 's't'i' 't'u'b' ','e'v'i's's'e'c'x'e' 't'i'b' 'a' 's'l'e'e'f''''d' 'n'o'i't'a'r'e'p'o' 'e'h't' 'r'e't'f'a' 'r'o's'r'u'c' 'e'h't' 'g'n'i't'a'd'p'U'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''u'b' ',''''''''''''''i'x'e'l'p'm'o'c' 'd'n'a' 'U'P'C' 'f'o' 'e't's'a'w' 'a' 'f'o' 't'i'b' 'a' 'e'k'i'l' 's'l'e'e'f' 't'i' 'o's' ','d'e'd'e'e'n' 't'o'n' 'y'l'l'a'u's'u'''''''u's' 's'i' 's'i'h'T' '/'/' '''n'''''n '' '' '''n // TODO: For consistency we might want to think about updating then // iterator'' true','''''''''''e'u'r't' ',' here.n } else {n // There isn't room. We'll need to add at least one new node to then // list. We could be a b'''''n ''' '/'/' 'it more careful here '' // Passing false to indicate we don't want the cursor updatedn // after this - it should remain at the end of the n' ''(mut cursor, offset) = self.iter_at_userpos(userpos'');'ewlyn // inserted content, which is *before* this end bit.'n ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''*''''''''''''''''''''.'t'i'b' 'd'n'e'''''''e'a' 's'i'h't' '*'''e'r'o'f'e'b' 's'i' 'h'c'i'h'w' ','t'n'e't'n'o'c' 'd'e't'r'e's'n'i' 'y'l'w'e'n' 'e'h't' 'f'o' 'd'n'e' 'e'h't' 't'a' 'n'i'a'm'e'r' 'd'l'u'o'h's' 't'i' '-' 's'i'h't' 'r'''''''t' 'e't'f'a' 'd'e't'a'd'p'u' 'r'o's'r'u'c' 'e'h't'''' 'o't' 't'n'a'w' 't'''n'o'd' 'e'w' 'e't'a'c'i'd'n'i' 'o't' 'e's'l'a'f' 'g'n'i's's'a'P' '/'/' 'and copy as much asn // possible into the current node - that would decrease the numbe'''''''e's'l'a'f' ','rn // of new nodes in some cases, but I don't think the performancen // difference will be large enough to justify the complexity.nn // If we're not at the end of the current node, w''''' 't'u'm''e'll'(' nee''''''''')'t'e's'f'f'o' ','d ''to removen // the end of the current node's data and reinsert it later.n let num_end_items'' = e_num_items - item_idx;nn let (end_items, end_usercount) = if num_end_items > 0 {n // We'll mark the items as deleted from the node, while leavingn // the data itself there for now to avoid a copy.nn // Note that if we wanted to, it would also be correct (andn // slightly more space efficient) to pack some of the newn // string's characters into this node after trimming it.n let end_items = &(*e).items[item_idx..e_num_items];n (*e).num_items = item_idx as u8;n let end_usercount = (*e).get_userlen() - cursor.entries[0].skip_usersize;nn cursor.update_offsets(self.head.height as usize, -(end_usercount as isize));nn // We need to trim the size off because we'll add the charactersn // back with insert_node_at.n self.num_usercount -= end_usercount;n self.num_items -= num_end_items;nn (Some(end_items), end_usercount)n } else {n (None, 0)n };nn // Now we insert new nodes containing the new character data. Then // data is broken into pieces with a maximum size of NODE_NUM_ITEMS.n // As further optimization, we could try and fit the last piece inton // the start of the subsequent node. That optimization hasn't beenn // added.n n for chunk in contents.chunks(NODE_NUM_ITEMS) {n let userlen = C::userlen_of_slice(chunk);n self.insert_node_at(cursor, chunk, userlen);n }nn // TODO: Consider recursively calling insert_at_iter() here insteadn // of making a whole new node for the remaining content.n if let Some(end_items) = end_items {n self.insert_node_at(cursor, end_items, end_usercount);n }n }n }nn /// Interestingly unlike the original, here we only care about specifyingn /// the number of removed items by counting them. We do not use usersize inn /// the deleted item count.n ///n /// If the deleted content occurs at the start of a node, the cursor passedn /// here must point to the end of the previous node, not the start of then /// current node.n unsafe fn del_at_iter(&mut self, cursor: &mut Cursor<C>, mut item_idx: usize, mut num_deleted_items: usize) {n if num_deleted_items == 0 { return; }nn let mut e = cursor.here_ptr();n while num_deleted_items > 0 {n if item_idx == (*e).num_items as usize {n let entry = (*e).first_skip_entry();n // End of current node. Skip to the start of the next one. We'ren // intentionally not updating the iterator because if we deleten // a whole node we need the iterator to point to the previousn // element. And if we only delete here, the iterator doesn'tn // need to be moved.n e = entry.node;n if e.is_null() { panic!('Cannot delete past the end of the list'); }n item_idx = 0;n }nn let e_num_items = (*e).num_items as usize;n let removed_here = min(num_deleted_items, e_num_items - item_idx);n n let height = (*e).height as usize;n let removed_userlen;nn if removed_here < e_num_items || e as *const _ == &self.head as *const _ {n // Just trim the node down.n let trailing_items = e_num_items - item_idx - removed_here;n n let c = &mut (*e).items;n removed_userlen = C::userlen_of_slice(&c[item_idx..item_idx + removed_here]);n if trailing_items > 0 {n c[..].copy_within(item_idx + removed_here..e_num_items, item_idx);n }nn (*e).num_items -= removed_here as u8;n self.num_items -= removed_here;n self.num_usercount -= removed_userlen;nn for s in (*e).nexts_mut() {n s.skip_usersize -= removed_userlen;n }n } else {n // Remove the node from the skip list entirely. e should be then // next node after the position of the iterator.n assert_ne!(cursor.here_ptr(), e);nn removed_userlen = (*e).get_userlen();n let next = (*e).first_skip_entry().node;nn for i in 0..(*e).height as usize {n let s = &mut (*cursor.entries[i].node).nexts_mut()[i];n s.node = (*e).nexts_mut()[i].node;n s.skip_usersize += (*e).nexts()[i].skip_usersize - removed_userlen;n }nn self.num_items -= (*e).num_items as usize;n self.num_usercount -= removed_userlen;nn Node::free(e);n e = next;n }nn for i in height..self.head.height as usize {n let s = &mut (*cursor.entries[i].node).nexts_mut()[i];n s.skip_usersize -= removed_userlen;n }nn num_deleted_items -= removed_here;n }n }nn pub fn replace_at(&mut self, mut start_userpos: usize, mut removed_items: usize, mut inserted_content: &[C::Item]) {n if removed_items == 0 && inserted_content.len() == 0 { return; }nn // For validation. This is where the cursor should end up.n // let expected_final_position = start_userpos + inserted_content.len() - removed_items;nn start_userpos = min(start_userpos, self.get_userlen());nn let mut cursor = self.iter_at_userpos(start_userpos);n let (mut index, offset) = unsafe { &*cursor.here_ptr() }.get_iter_idx(cursor.entries[0].skip_usersize, false);n assert_eq!(offset, 0, 'Splitting nodes not yet supported');nn // Replace as many items from removed_items as we can with inserted_content.n unsafe {n let mut replaced_items = min(removed_items, inserted_content.len());n removed_items -= replaced_items;nn while replaced_items > 0 {n let mut e = cursor.here_ptr();n if index == (*e).num_items as usize {n // Move to the next item.n e = cursor.advance_node();n if e.is_null() { panic!('Cannot replace past the end of the list'); }n index = 0;n }nn let e_num_items = (*e).num_items as usize;n let replaced_items_here = min(replaced_items, e_num_items - index);nn let old_items = &mut (*e).items[index..index + replaced_items_here];n let new_items = &inserted_content[0..replaced_items_here];nn // Replace the items themselves.n old_items.copy_from_slice(new_items);nn // And bookkeeping. Bookkeeping forever.n let new_usersize = C::userlen_of_slice(new_items);n let usersize_delta = new_usersize as isize - C::userlen_of_slice(old_items) as isize;n if usersize_delta != 0 {n cursor.update_offsets(self.head.height as usize, usersize_delta)n }nn inserted_content = &inserted_content[replaced_items_here..];n replaced_items -= replaced_items_here;n // We'll hop to the next Node at the start of the next loopn // iteration if needed.n index += replaced_items_here;nn for i in 0..self.head.height as usize {n cursor.entries[i].skip_usersize += new_usersize;n }n cursor.userpos += new_usersize;n }nn // Ok now one of two things must be true. Either we've run out ofn // items to remove, or we've run out of items to insert.n if inserted_content.len() > 0 {n // Insert!n debug_assert!(removed_items == 0);n self.insert_at_iter(&mut cursor, index, inserted_content);n } else if removed_items > 0 {n self.del_at_iter(&mut cursor, index, removed_items);n }n }nn // TODO: Assert that the iterator is after replaced content.n // #[cfg(debug_assertions)] {n // let c2 = self.iter_at_userpos(expected_final_position);n // if &cursor != &c2 { panic!('Invalid cursor after replace'); }n // }n }nn pub fn insert_at(&mut self, mut userpos: usize, contents: &[C::Item]) {n if contents.len() == 0 { return; }n n userpos = min(userpos, self.get_userlen());n let mut cursor = self.iter_at_userpos(userpos);n let (index, offset) = unsafe { &*cursor.here_ptr() }.get_iter_idx(cursor.entries[0].skip_usersize, false);n assert_eq!(offset, 0, 'Splitting nodes not yet supported');n unsafe { self.insert_at_iter(&mut cursor, index, contents); }nn #[cfg(debug_assertions)] {n let c2 = self.iter_at_userpos(userpos + C::userlen_of_slice(contents));n if &cursor != &c2 { panic!('Invalid cursor after insert'); }n }n // TODO: Assert that the iterator now points after removed content.n }nn pub fn del_at(&mut self, mut userpos: usize, num_items: usize) {n userpos = min(userpos, self.get_userlen());n // We can't easily trim num_items.n // num_items = min(length, self.num_chars() - pos);n if num_items == 0 { return; }nn let mut cursor = self.iter_at_userpos(userpos);n let (index, offset) = unsafe { &*cursor.here_ptr() }.get_iter_idx(cursor.entries[0].skip_usersize, false);n assert_eq!(offset, 0, 'Splitting nodes not yet supported');nn unsafe { self.del_at_iter(&mut cursor, index, num_items); }n // TODO: Assert that the iterator remains where it was.n }n}nnnimpl<C: ListConfig> SkipList<C> where C::Item: PartialEq {n pub fn eq_list(&self, other: &[C::Item]) -> bool {n let mut pos = 0;n let other_len = other.len();nn for node in self.iter() {n let my_data = node.content_slice();n let my_len = my_data.len();nn if pos + my_len > other_len || my_data != &other[pos..pos + my_data.len()] {n return falsen }n pos += my_data.len();n }nn return pos == other_len;n }n}nnimpl<C: ListConfig> Drop for SkipList<C> {n fn drop(&mut self) {n let mut node = self.head.first_skip_entry().node;n unsafe {n while !node.is_null() {n let next = (*node).first_skip_entry().node;n Node::free(node);n node = next;n }n }n }n}nnnimpl<C: ListConfig> From<&[C::Item]> for SkipList<C> {n fn from(s: &[C::Item]) -> SkipList<C> {n SkipList::new_from_slice(s)n }n}nnimpl<C: ListConfig> From<Vec<C::Item>> for SkipList<C> {n fn from(s: Vec<C::Item>) -> SkipList<C> {n SkipList::new_from_slice(s.as_slice())n }n}nnimpl<C: ListConfig> Into<Vec<C::Item>> for &SkipList<C> {n fn into(self) -> Vec<C::Item> {n let mut content = Vec::with_capacity(self.num_items);nn for node in self.iter() {n content.extend(node.content_slice().iter());n }nn contentn }n}nnimpl<C: ListConfig> SkipList<C> where C::Item: std::fmt::Debug {n // TODO: Don't export this.n pub fn print(&self) {n println!('items: {}tuserlen: {}, height: {}', self.num_items, self.get_userlen(), self.head.height);nn print!('HEAD:');n for s in self.head.nexts() {n print!(' |{} ', s.skip_usersize);n }n println!('');nn for (i, node) in self.iter().enumerate() {n print!('{}:', i);n for s in node.nexts() {n print!(' |{} ', s.skip_usersize);n }n println!(' : {:?}', node.content_slice());n }n }n}nn// impl<T: Default + Copy, F: Fn(&T) -> usize> PartialEq for SkipList<T, F> {n// // This is quite complicated. It would be cleaner to just write a bytesn// // iterator, then iterate over the bytes of both strings comparing along then// // way.n// // However, this should be faster because it can memcmp().nn// // Another way to implement this would be to rewrite it as a comparison withn// // an iterator over &str. Then the rope vs rope comparison would be trivial,n// // but also we could add comparison functions with a single &str and stuffn// // very easily.n// fn eq(&self, other: &SkipList<T, F>) -> bool {n// if self.num_items != other.num_itemsn// || self.num_chars() != other.num_chars() {n// return falsen// }nn// let mut other_iter = other.iter().map(|n| { n.as_str() });nn// let mut os = other_iter.next();n// let mut opos: usize = 0; // Byte offset in os.n// for n in self.iter() {n// let s = n.as_str();n// let mut pos: usize = 0; // Current byte offset in sn// debug_assert_eq!(s.len(), n.num_bytes as usize);nn// // Walk s.len() bytes through the other ropen// while pos < n.num_bytes as usize {n// if let Some(oss) = os {n// let amt = min(s.len() - pos, oss.len() - opos);n// // println!('iter slen {} pos {} osslen {} amt {}', s.len(), pos, oss.len(), amt);nn// if &s[pos..pos+amt] != &oss[opos..opos+amt] {n// return falsen// }nn// pos += amt;n// opos += amt;n// debug_assert!(opos <= oss.len());nn// if opos == oss.len() {n// os = other_iter.next();n// opos = 0;n// }n// } else {n// panic!('Internal string length does not match');n// }n// }n// }nn// truen// }n// }n// impl<T: Default + Copy, F: Fn(&T) -> usize> Eq for SkipList<T, F> {}nn// impl<T: Default + Copy, F> Clone for SkipList<T, F> where F: Fn(&T) -> usize {n// fn clone(&self) -> Self {n// let mut r = SkipList::new(self.get_usersize);n// r.num_items = self.num_items;n// let head_str = self.head.as_str();n// r.head.items[..head_str.len()].copy_from_slice(head_str.as_bytes());n// r.head.num_bytes = self.head.num_bytes;n// r.head.height = self.head.height;n n// {n// // I could just edit the overflow memory directly, but this is safern// // because of aliasing rules.n// let head_nexts = r.head.nexts_mut();n// for i in 0..self.head.height as usize {n// head_nexts[i].skip_items = self.nexts[i].skip_items;n// }n// }nn// let mut nodes = [&mut r.head as *mut Node; MAX_HEIGHT];nn// // The first node the iterator will return is the head. Ignore it.n// let mut iter = self.iter();n// iter.next();n// for other in iter {n// // This also sets height.n// let height = other.height;n// let node = Node::alloc_with_height(height);n// unsafe {n// (*node).num_bytes = other.num_bytes;n// let len = other.num_bytes as usize;n// (*node).items[..len].copy_from_slice(&other.items[..len]);nn// let other_nexts = other.nexts();n// let nexts = (*node).nexts_mut();n// for i in 0..height as usize {n// nexts[i].skip_items = other_nexts[i].skip_items;n// (*nodes[i]).nexts_mut()[i].node = node;n// nodes[i] = node;n// }n// }n// }nn// rn// }n// }n' |