java_string/
owned.rs

1use std::borrow::{Borrow, BorrowMut, Cow};
2use std::collections::{Bound, TryReserveError};
3use std::convert::Infallible;
4use std::fmt::{Debug, Display, Formatter, Write};
5use std::hash::{Hash, Hasher};
6use std::iter::FusedIterator;
7use std::ops::{
8    Add, AddAssign, Deref, DerefMut, Index, IndexMut, Range, RangeBounds, RangeFrom, RangeFull,
9    RangeInclusive, RangeTo, RangeToInclusive,
10};
11use std::rc::Rc;
12use std::str::FromStr;
13use std::sync::Arc;
14use std::{ptr, slice};
15
16use crate::validations::{
17    run_utf8_full_validation_from_semi, run_utf8_semi_validation, to_range_checked,
18};
19use crate::{Chars, FromUtf8Error, JavaCodePoint, JavaStr, Utf8Error};
20
21#[derive(Default, PartialEq, PartialOrd, Eq, Ord)]
22pub struct JavaString {
23    vec: Vec<u8>,
24}
25
26#[allow(clippy::multiple_inherent_impl)]
27impl JavaString {
28    #[inline]
29    #[must_use]
30    pub const fn new() -> JavaString {
31        JavaString { vec: Vec::new() }
32    }
33
34    #[inline]
35    #[must_use]
36    pub fn with_capacity(capacity: usize) -> JavaString {
37        JavaString {
38            vec: Vec::with_capacity(capacity),
39        }
40    }
41
42    /// Converts `vec` to a `JavaString` if it is fully-valid UTF-8, i.e. UTF-8
43    /// without surrogate code points. See [`String::from_utf8`].
44    #[inline]
45    pub fn from_full_utf8(vec: Vec<u8>) -> Result<JavaString, FromUtf8Error> {
46        match std::str::from_utf8(&vec) {
47            Ok(..) => Ok(JavaString { vec }),
48            Err(e) => Err(FromUtf8Error {
49                bytes: vec,
50                error: e.into(),
51            }),
52        }
53    }
54
55    /// Converts `vec` to a `JavaString` if it is semi-valid UTF-8, i.e. UTF-8
56    /// with surrogate code points.
57    ///
58    /// ```
59    /// # use java_string::{JavaCodePoint, JavaString};
60    ///
61    /// assert_eq!(
62    ///     JavaString::from_semi_utf8(b"Hello World!".to_vec()).unwrap(),
63    ///     "Hello World!"
64    /// );
65    /// assert_eq!(
66    ///     JavaString::from_semi_utf8(vec![0xf0, 0x9f, 0x92, 0x96]).unwrap(),
67    ///     "💖"
68    /// );
69    /// assert_eq!(
70    ///     JavaString::from_semi_utf8(vec![0xed, 0xa0, 0x80]).unwrap(),
71    ///     JavaString::from(JavaCodePoint::from_u32(0xd800).unwrap())
72    /// );
73    /// assert!(JavaString::from_semi_utf8(vec![0xed]).is_err());
74    /// ```
75    pub fn from_semi_utf8(vec: Vec<u8>) -> Result<JavaString, FromUtf8Error> {
76        match run_utf8_semi_validation(&vec) {
77            Ok(..) => Ok(JavaString { vec }),
78            Err(err) => Err(FromUtf8Error {
79                bytes: vec,
80                error: err,
81            }),
82        }
83    }
84
85    /// Converts `v` to a `Cow<JavaStr>`, replacing invalid semi-UTF-8 with the
86    /// replacement character �.
87    ///
88    /// ```
89    /// # use std::borrow::Cow;
90    /// # use java_string::{JavaStr, JavaString};
91    ///
92    /// let sparkle_heart = [0xf0, 0x9f, 0x92, 0x96];
93    /// let result = JavaString::from_semi_utf8_lossy(&sparkle_heart);
94    /// assert!(matches!(result, Cow::Borrowed(_)));
95    /// assert_eq!(result, JavaStr::from_str("💖"));
96    ///
97    /// let foobar_with_error = [b'f', b'o', b'o', 0xed, b'b', b'a', b'r'];
98    /// let result = JavaString::from_semi_utf8_lossy(&foobar_with_error);
99    /// assert!(matches!(result, Cow::Owned(_)));
100    /// assert_eq!(result, JavaStr::from_str("foo�bar"));
101    /// ```
102    #[must_use]
103    pub fn from_semi_utf8_lossy(v: &[u8]) -> Cow<'_, JavaStr> {
104        const REPLACEMENT: &str = "\u{FFFD}";
105
106        match run_utf8_semi_validation(v) {
107            Ok(()) => unsafe {
108                // SAFETY: validation succeeded
109                Cow::Borrowed(JavaStr::from_semi_utf8_unchecked(v))
110            },
111            Err(error) => {
112                let mut result = unsafe {
113                    // SAFETY: validation succeeded up to this index
114                    JavaString::from_semi_utf8_unchecked(
115                        v.get_unchecked(..error.valid_up_to).to_vec(),
116                    )
117                };
118                result.push_str(REPLACEMENT);
119                let mut index = error.valid_up_to + error.error_len.unwrap_or(1) as usize;
120                loop {
121                    match run_utf8_semi_validation(&v[index..]) {
122                        Ok(()) => {
123                            unsafe {
124                                // SAFETY: validation succeeded
125                                result.push_java_str(JavaStr::from_semi_utf8_unchecked(&v[index..]))
126                            };
127                            return Cow::Owned(result);
128                        }
129                        Err(error) => {
130                            unsafe {
131                                // SAFETY: validation succeeded up to this index
132                                result.push_java_str(JavaStr::from_semi_utf8_unchecked(
133                                    v.get_unchecked(index..index + error.valid_up_to),
134                                ))
135                            };
136                            result.push_str(REPLACEMENT);
137                            index += error.valid_up_to + error.error_len.unwrap_or(1) as usize;
138                        }
139                    }
140                }
141            }
142        }
143    }
144
145    /// # Safety
146    ///
147    /// The parameter must be in semi-valid UTF-8 format, that is, UTF-8 plus
148    /// surrogate code points.
149    #[inline]
150    #[must_use]
151    pub unsafe fn from_semi_utf8_unchecked(bytes: Vec<u8>) -> JavaString {
152        JavaString { vec: bytes }
153    }
154
155    /// See [`String::into_bytes`].
156    #[inline]
157    #[must_use]
158    pub fn into_bytes(self) -> Vec<u8> {
159        self.vec
160    }
161
162    /// See [`String::as_str`].
163    #[inline]
164    #[must_use]
165    pub const fn as_java_str(&self) -> &JavaStr {
166        unsafe {
167            // SAFETY: this str has semi-valid UTF-8
168            JavaStr::from_semi_utf8_unchecked(self.vec.as_slice())
169        }
170    }
171
172    /// See [`String::as_mut_str`].
173    #[inline]
174    #[must_use]
175    pub const fn as_mut_java_str(&mut self) -> &mut JavaStr {
176        unsafe {
177            // SAFETY: this str has semi-valid UTF-8
178            JavaStr::from_semi_utf8_unchecked_mut(self.vec.as_mut_slice())
179        }
180    }
181
182    /// Tries to convert this `JavaString` to a `String`, returning an error if
183    /// it is not fully valid UTF-8, i.e. has no surrogate code points.
184    ///
185    /// ```
186    /// # use java_string::{JavaCodePoint, JavaString};
187    ///
188    /// assert_eq!(
189    ///     JavaString::from("Hello World!").into_string().unwrap(),
190    ///     "Hello World!"
191    /// );
192    /// assert_eq!(
193    ///     JavaString::from("abc\0ℝ💣").into_string().unwrap(),
194    ///     "abc\0ℝ💣"
195    /// );
196    ///
197    /// let string_with_error = JavaString::from("abc")
198    ///     + JavaString::from(JavaCodePoint::from_u32(0xd800).unwrap()).as_java_str();
199    /// assert!(string_with_error.into_string().is_err());
200    /// ```
201    pub fn into_string(self) -> Result<String, Utf8Error> {
202        run_utf8_full_validation_from_semi(self.as_bytes()).map(|()| unsafe {
203            // SAFETY: validation succeeded
204            self.into_string_unchecked()
205        })
206    }
207
208    /// # Safety
209    ///
210    /// This string must be fully valid UTF-8, i.e. have no surrogate code
211    /// points.
212    #[inline]
213    #[must_use]
214    pub unsafe fn into_string_unchecked(self) -> String {
215        // SAFETY: preconditions checked by caller
216        String::from_utf8_unchecked(self.vec)
217    }
218
219    /// See [`String::push_str`].
220    #[inline]
221    pub fn push_java_str(&mut self, string: &JavaStr) {
222        self.vec.extend_from_slice(string.as_bytes())
223    }
224
225    /// See [`String::push_str`].
226    #[inline]
227    pub fn push_str(&mut self, string: &str) {
228        self.vec.extend_from_slice(string.as_bytes())
229    }
230
231    /// See [`String::extend_from_within`]
232    #[inline]
233    pub fn extend_from_within<R>(&mut self, src: R)
234    where
235        R: RangeBounds<usize>,
236    {
237        let src @ Range { start, end } = to_range_checked(src, ..self.len());
238
239        assert!(self.is_char_boundary(start));
240        assert!(self.is_char_boundary(end));
241
242        self.vec.extend_from_within(src);
243    }
244
245    /// See [`String::capacity`].
246    #[inline]
247    #[must_use]
248    pub const fn capacity(&self) -> usize {
249        self.vec.capacity()
250    }
251
252    /// See [`String::reserve`].
253    #[inline]
254    pub fn reserve(&mut self, additional: usize) {
255        self.vec.reserve(additional)
256    }
257
258    /// See [`String::reserve_exact`].
259    #[inline]
260    pub fn reserve_exact(&mut self, additional: usize) {
261        self.vec.reserve_exact(additional)
262    }
263
264    /// See [`String::try_reserve`].
265    #[inline]
266    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
267        self.vec.try_reserve(additional)
268    }
269
270    /// See [`String::try_reserve_exact`].
271    #[inline]
272    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
273        self.vec.try_reserve_exact(additional)
274    }
275
276    /// See [`String::shrink_to_fit`].
277    #[inline]
278    pub fn shrink_to_fit(&mut self) {
279        self.vec.shrink_to_fit()
280    }
281
282    /// See [`String::shrink_to`].
283    #[inline]
284    pub fn shrink_to(&mut self, min_capacity: usize) {
285        self.vec.shrink_to(min_capacity)
286    }
287
288    /// See [`String::push`].
289    #[inline]
290    pub fn push(&mut self, ch: char) {
291        match ch.len_utf8() {
292            1 => self.vec.push(ch as u8),
293            _ => self
294                .vec
295                .extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()),
296        }
297    }
298
299    /// See [`String::push`].
300    #[inline]
301    pub fn push_java(&mut self, ch: JavaCodePoint) {
302        match ch.len_utf8() {
303            1 => self.vec.push(ch.as_u32() as u8),
304            _ => self.vec.extend_from_slice(ch.encode_semi_utf8(&mut [0; 4])),
305        }
306    }
307
308    /// See [`String::as_bytes`].
309    #[inline]
310    #[must_use]
311    pub const fn as_bytes(&self) -> &[u8] {
312        self.vec.as_slice()
313    }
314
315    /// See [`String::truncate`].
316    #[inline]
317    pub fn truncate(&mut self, new_len: usize) {
318        if new_len <= self.len() {
319            assert!(self.is_char_boundary(new_len));
320            self.vec.truncate(new_len)
321        }
322    }
323
324    /// See [`String::pop`].
325    ///
326    /// ```
327    /// # use java_string::JavaString;
328    ///
329    /// let mut str = JavaString::from("Hello World!");
330    /// assert_eq!(str.pop().unwrap(), '!');
331    /// assert_eq!(str, "Hello World");
332    ///
333    /// let mut str = JavaString::from("東京");
334    /// assert_eq!(str.pop().unwrap(), '京');
335    /// assert_eq!(str, "東");
336    ///
337    /// assert!(JavaString::new().pop().is_none());
338    /// ```
339    #[inline]
340    pub fn pop(&mut self) -> Option<JavaCodePoint> {
341        let ch = self.chars().next_back()?;
342        let newlen = self.len() - ch.len_utf8();
343        unsafe { self.vec.set_len(newlen) };
344        Some(ch)
345    }
346
347    /// See [`String::remove`].
348    ///
349    /// ```
350    /// # use java_string::JavaString;
351    ///
352    /// let mut str = JavaString::from("Hello World!");
353    /// assert_eq!(str.remove(5), ' ');
354    /// assert_eq!(str, "HelloWorld!");
355    ///
356    /// let mut str = JavaString::from("Hello 🦀 World!");
357    /// assert_eq!(str.remove(6), '🦀');
358    /// assert_eq!(str, "Hello  World!");
359    /// ```
360    /// ```should_panic
361    /// # use java_string::JavaString;
362    /// // Should panic
363    /// JavaString::new().remove(0);
364    /// ```
365    /// ```should_panic
366    /// # use java_string::JavaString;
367    /// // Should panic
368    /// JavaString::from("🦀").remove(1);
369    /// ```
370    #[inline]
371    pub fn remove(&mut self, idx: usize) -> JavaCodePoint {
372        let Some(ch) = self[idx..].chars().next() else {
373            panic!("cannot remove a char from the end of a string")
374        };
375
376        let next = idx + ch.len_utf8();
377        let len = self.len();
378        unsafe {
379            ptr::copy(
380                self.vec.as_ptr().add(next),
381                self.vec.as_mut_ptr().add(idx),
382                len - next,
383            );
384            self.vec.set_len(len - (next - idx))
385        };
386        ch
387    }
388
389    /// See [`String::retain`].
390    ///
391    /// ```
392    /// # use java_string::{JavaCodePoint, JavaString};
393    ///
394    /// let mut str = JavaString::from("Hello 🦀 World!");
395    /// str.retain(|ch| !ch.is_ascii_uppercase());
396    /// assert_eq!(str, "ello 🦀 orld!");
397    /// str.retain(JavaCodePoint::is_ascii);
398    /// assert_eq!(str, "ello  orld!");
399    /// ```
400    #[inline]
401    pub fn retain<F>(&mut self, mut f: F)
402    where
403        F: FnMut(JavaCodePoint) -> bool,
404    {
405        struct SetLenOnDrop<'a> {
406            s: &'a mut JavaString,
407            idx: usize,
408            del_bytes: usize,
409        }
410
411        impl Drop for SetLenOnDrop<'_> {
412            #[inline]
413            fn drop(&mut self) {
414                let new_len = self.idx - self.del_bytes;
415                debug_assert!(new_len <= self.s.len());
416                unsafe { self.s.vec.set_len(new_len) };
417            }
418        }
419
420        let len = self.len();
421        let mut guard = SetLenOnDrop {
422            s: self,
423            idx: 0,
424            del_bytes: 0,
425        };
426
427        while guard.idx < len {
428            // SAFETY: `guard.idx` is positive-or-zero and less that len so the
429            // `get_unchecked` is in bound. `self` is valid UTF-8 like string
430            // and the returned slice starts at a unicode code point so the
431            // `Chars` always return one character.
432            let ch = unsafe {
433                guard
434                    .s
435                    .get_unchecked(guard.idx..len)
436                    .chars()
437                    .next()
438                    .unwrap_unchecked()
439            };
440            let ch_len = ch.len_utf8();
441
442            if !f(ch) {
443                guard.del_bytes += ch_len;
444            } else if guard.del_bytes > 0 {
445                // SAFETY: `guard.idx` is in bound and `guard.del_bytes` represent the number of
446                // bytes that are erased from the string so the resulting `guard.idx -
447                // guard.del_bytes` always represent a valid unicode code point.
448                //
449                // `guard.del_bytes` >= `ch.len_utf8()`, so taking a slice with `ch.len_utf8()`
450                // len is safe.
451                ch.encode_semi_utf8(unsafe {
452                    slice::from_raw_parts_mut(
453                        guard.s.as_mut_ptr().add(guard.idx - guard.del_bytes),
454                        ch.len_utf8(),
455                    )
456                });
457            }
458
459            // Point idx to the next char
460            guard.idx += ch_len;
461        }
462
463        drop(guard);
464    }
465
466    /// See [`String::insert`].
467    ///
468    /// ```
469    /// # use java_string::JavaString;
470    /// let mut s = JavaString::from("foo");
471    /// s.insert(3, 'a');
472    /// s.insert(4, 'r');
473    /// s.insert(3, 'b');
474    /// assert_eq!(s, "foobar");
475    /// ```
476    #[inline]
477    pub fn insert(&mut self, idx: usize, ch: char) {
478        assert!(self.is_char_boundary(idx));
479        let mut bits = [0; 4];
480        let bits = ch.encode_utf8(&mut bits).as_bytes();
481
482        unsafe {
483            self.insert_bytes(idx, bits);
484        }
485    }
486
487    /// See [`String::insert`].
488    #[inline]
489    pub fn insert_java(&mut self, idx: usize, ch: JavaCodePoint) {
490        assert!(self.is_char_boundary(idx));
491        let mut bits = [0; 4];
492        let bits = ch.encode_semi_utf8(&mut bits);
493
494        unsafe {
495            self.insert_bytes(idx, bits);
496        }
497    }
498
499    #[inline]
500    unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
501        let len = self.len();
502        let amt = bytes.len();
503        self.vec.reserve(amt);
504
505        unsafe {
506            ptr::copy(
507                self.vec.as_ptr().add(idx),
508                self.vec.as_mut_ptr().add(idx + amt),
509                len - idx,
510            );
511            ptr::copy_nonoverlapping(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt);
512            self.vec.set_len(len + amt);
513        }
514    }
515
516    /// See [`String::insert_str`].
517    ///
518    /// ```
519    /// # use java_string::JavaString;
520    /// let mut s = JavaString::from("bar");
521    /// s.insert_str(0, "foo");
522    /// assert_eq!(s, "foobar");
523    /// ```
524    #[inline]
525    pub fn insert_str(&mut self, idx: usize, string: &str) {
526        assert!(self.is_char_boundary(idx));
527
528        unsafe {
529            self.insert_bytes(idx, string.as_bytes());
530        }
531    }
532
533    /// See [`String::insert_str`].
534    pub fn insert_java_str(&mut self, idx: usize, string: &JavaStr) {
535        assert!(self.is_char_boundary(idx));
536
537        unsafe {
538            self.insert_bytes(idx, string.as_bytes());
539        }
540    }
541
542    /// See [`String::as_mut_vec`].
543    ///
544    /// # Safety
545    ///
546    /// The returned `Vec` must not have invalid UTF-8 written to it, besides
547    /// surrogate pairs.
548    #[inline]
549    pub const unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8> {
550        &mut self.vec
551    }
552
553    /// See [`String::len`].
554    #[inline]
555    #[must_use]
556    pub const fn len(&self) -> usize {
557        self.vec.len()
558    }
559
560    /// See [`String::is_empty`].
561    #[inline]
562    #[must_use]
563    pub const fn is_empty(&self) -> bool {
564        self.len() == 0
565    }
566
567    /// See [`String::split_off`].
568    ///
569    /// ```
570    /// # use java_string::JavaString;
571    /// let mut hello = JavaString::from("Hello World!");
572    /// let world = hello.split_off(6);
573    /// assert_eq!(hello, "Hello ");
574    /// assert_eq!(world, "World!");
575    /// ```
576    /// ```should_panic
577    /// # use java_string::JavaString;
578    /// let mut s = JavaString::from("🦀");
579    /// // Should panic
580    /// let _ = s.split_off(1);
581    /// ```
582    #[inline]
583    #[must_use]
584    pub fn split_off(&mut self, at: usize) -> JavaString {
585        assert!(self.is_char_boundary(at));
586        let other = self.vec.split_off(at);
587        unsafe { JavaString::from_semi_utf8_unchecked(other) }
588    }
589
590    /// See [`String::clear`].
591    #[inline]
592    pub fn clear(&mut self) {
593        self.vec.clear();
594    }
595
596    /// See [`String::drain`].
597    ///
598    /// ```
599    /// # use java_string::JavaString;
600    ///
601    /// let mut s = JavaString::from("α is alpha, β is beta");
602    /// let beta_offset = s.find('β').unwrap_or(s.len());
603    ///
604    /// // Remove the range up until the β from the string
605    /// let t: JavaString = s.drain(..beta_offset).collect();
606    /// assert_eq!(t, "α is alpha, ");
607    /// assert_eq!(s, "β is beta");
608    ///
609    /// // A full range clears the string, like `clear()` does
610    /// s.drain(..);
611    /// assert_eq!(s, "");
612    /// ```
613    #[inline]
614    pub fn drain<R>(&mut self, range: R) -> Drain<'_>
615    where
616        R: RangeBounds<usize>,
617    {
618        // Memory safety: see String::drain
619        let Range { start, end } = to_range_checked(range, ..self.len());
620        assert!(self.is_char_boundary(start));
621        assert!(self.is_char_boundary(end));
622
623        // Take out two simultaneous borrows. The &mut String won't be accessed
624        // until iteration is over, in Drop.
625        let self_ptr = self as *mut _;
626        // SAFETY: `to_range_checked` and `is_char_boundary` do the appropriate bounds
627        // checks.
628        let chars_iter = unsafe { self.get_unchecked(start..end) }.chars();
629
630        Drain {
631            start,
632            end,
633            iter: chars_iter,
634            string: self_ptr,
635        }
636    }
637
638    /// See [`String::replace_range`].
639    ///
640    /// ```
641    /// # use java_string::JavaString;
642    ///
643    /// let mut s = JavaString::from("α is alpha, β is beta");
644    /// let beta_offset = s.find('β').unwrap_or(s.len());
645    ///
646    /// // Replace the range up until the β from the string
647    /// s.replace_range(..beta_offset, "Α is capital alpha; ");
648    /// assert_eq!(s, "Α is capital alpha; β is beta");
649    /// ```
650    /// ```should_panic
651    /// # use java_string::JavaString;
652    /// let mut s = JavaString::from("α is alpha, β is beta");
653    /// // Should panic
654    /// s.replace_range(..1, "Α is capital alpha; ");
655    /// ```
656    pub fn replace_range<R>(&mut self, range: R, replace_with: &str)
657    where
658        R: RangeBounds<usize>,
659    {
660        self.replace_range_java(range, JavaStr::from_str(replace_with))
661    }
662
663    /// See [`String::replace_range`].
664    pub fn replace_range_java<R>(&mut self, range: R, replace_with: &JavaStr)
665    where
666        R: RangeBounds<usize>,
667    {
668        let start = range.start_bound();
669        match start {
670            Bound::Included(&n) => assert!(self.is_char_boundary(n)),
671            Bound::Excluded(&n) => assert!(self.is_char_boundary(n + 1)),
672            Bound::Unbounded => {}
673        };
674        let end = range.end_bound();
675        match end {
676            Bound::Included(&n) => assert!(self.is_char_boundary(n + 1)),
677            Bound::Excluded(&n) => assert!(self.is_char_boundary(n)),
678            Bound::Unbounded => {}
679        };
680
681        unsafe { self.as_mut_vec() }.splice((start, end), replace_with.bytes());
682    }
683
684    /// See [`String::into_boxed_str`].
685    #[inline]
686    #[must_use]
687    pub fn into_boxed_str(self) -> Box<JavaStr> {
688        let slice = self.vec.into_boxed_slice();
689        unsafe { JavaStr::from_boxed_semi_utf8_unchecked(slice) }
690    }
691
692    /// See [`String::leak`].
693    #[inline]
694    pub fn leak<'a>(self) -> &'a mut JavaStr {
695        let slice = self.vec.leak();
696        unsafe { JavaStr::from_semi_utf8_unchecked_mut(slice) }
697    }
698}
699
700impl Add<&str> for JavaString {
701    type Output = JavaString;
702
703    #[inline]
704    fn add(mut self, rhs: &str) -> Self::Output {
705        self.push_str(rhs);
706        self
707    }
708}
709
710impl Add<&JavaStr> for JavaString {
711    type Output = JavaString;
712
713    #[inline]
714    fn add(mut self, rhs: &JavaStr) -> Self::Output {
715        self.push_java_str(rhs);
716        self
717    }
718}
719
720impl AddAssign<&str> for JavaString {
721    #[inline]
722    fn add_assign(&mut self, rhs: &str) {
723        self.push_str(rhs);
724    }
725}
726
727impl AddAssign<&JavaStr> for JavaString {
728    #[inline]
729    fn add_assign(&mut self, rhs: &JavaStr) {
730        self.push_java_str(rhs);
731    }
732}
733
734impl AsMut<JavaStr> for JavaString {
735    #[inline]
736    fn as_mut(&mut self) -> &mut JavaStr {
737        self.as_mut_java_str()
738    }
739}
740
741impl AsRef<[u8]> for JavaString {
742    #[inline]
743    fn as_ref(&self) -> &[u8] {
744        self.as_bytes()
745    }
746}
747
748impl AsRef<JavaStr> for JavaString {
749    #[inline]
750    fn as_ref(&self) -> &JavaStr {
751        self.as_java_str()
752    }
753}
754
755impl Borrow<JavaStr> for JavaString {
756    #[inline]
757    fn borrow(&self) -> &JavaStr {
758        self.as_java_str()
759    }
760}
761
762impl BorrowMut<JavaStr> for JavaString {
763    #[inline]
764    fn borrow_mut(&mut self) -> &mut JavaStr {
765        self.as_mut_java_str()
766    }
767}
768
769impl Clone for JavaString {
770    #[inline]
771    fn clone(&self) -> Self {
772        JavaString {
773            vec: self.vec.clone(),
774        }
775    }
776
777    #[inline]
778    fn clone_from(&mut self, source: &Self) {
779        self.vec.clone_from(&source.vec)
780    }
781}
782
783impl Debug for JavaString {
784    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
785        Debug::fmt(&**self, f)
786    }
787}
788
789impl Deref for JavaString {
790    type Target = JavaStr;
791
792    #[inline]
793    fn deref(&self) -> &Self::Target {
794        self.as_java_str()
795    }
796}
797
798impl DerefMut for JavaString {
799    #[inline]
800    fn deref_mut(&mut self) -> &mut Self::Target {
801        self.as_mut_java_str()
802    }
803}
804
805impl Display for JavaString {
806    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
807        Display::fmt(&**self, f)
808    }
809}
810
811impl Extend<char> for JavaString {
812    fn extend<T: IntoIterator<Item = char>>(&mut self, iter: T) {
813        let iterator = iter.into_iter();
814        let (lower_bound, _) = iterator.size_hint();
815        self.reserve(lower_bound);
816        iterator.for_each(move |c| self.push(c));
817    }
818}
819
820impl Extend<JavaCodePoint> for JavaString {
821    fn extend<T: IntoIterator<Item = JavaCodePoint>>(&mut self, iter: T) {
822        let iterator = iter.into_iter();
823        let (lower_bound, _) = iterator.size_hint();
824        self.reserve(lower_bound);
825        iterator.for_each(move |c| self.push_java(c));
826    }
827}
828
829impl Extend<String> for JavaString {
830    fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {
831        iter.into_iter().for_each(move |s| self.push_str(&s));
832    }
833}
834
835impl Extend<JavaString> for JavaString {
836    fn extend<T: IntoIterator<Item = JavaString>>(&mut self, iter: T) {
837        iter.into_iter().for_each(move |s| self.push_java_str(&s));
838    }
839}
840
841impl<'a> Extend<&'a char> for JavaString {
842    fn extend<T: IntoIterator<Item = &'a char>>(&mut self, iter: T) {
843        self.extend(iter.into_iter().copied())
844    }
845}
846
847impl<'a> Extend<&'a JavaCodePoint> for JavaString {
848    fn extend<T: IntoIterator<Item = &'a JavaCodePoint>>(&mut self, iter: T) {
849        self.extend(iter.into_iter().copied())
850    }
851}
852
853impl<'a> Extend<&'a str> for JavaString {
854    fn extend<T: IntoIterator<Item = &'a str>>(&mut self, iter: T) {
855        iter.into_iter().for_each(move |s| self.push_str(s));
856    }
857}
858
859impl<'a> Extend<&'a JavaStr> for JavaString {
860    fn extend<T: IntoIterator<Item = &'a JavaStr>>(&mut self, iter: T) {
861        iter.into_iter().for_each(move |s| self.push_java_str(s));
862    }
863}
864
865impl Extend<Box<str>> for JavaString {
866    fn extend<T: IntoIterator<Item = Box<str>>>(&mut self, iter: T) {
867        iter.into_iter().for_each(move |s| self.push_str(&s));
868    }
869}
870
871impl Extend<Box<JavaStr>> for JavaString {
872    fn extend<T: IntoIterator<Item = Box<JavaStr>>>(&mut self, iter: T) {
873        iter.into_iter().for_each(move |s| self.push_java_str(&s));
874    }
875}
876
877impl<'a> Extend<Cow<'a, str>> for JavaString {
878    fn extend<T: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: T) {
879        iter.into_iter().for_each(move |s| self.push_str(&s));
880    }
881}
882
883impl<'a> Extend<Cow<'a, JavaStr>> for JavaString {
884    fn extend<T: IntoIterator<Item = Cow<'a, JavaStr>>>(&mut self, iter: T) {
885        iter.into_iter().for_each(move |s| self.push_java_str(&s));
886    }
887}
888
889impl From<String> for JavaString {
890    #[inline]
891    fn from(value: String) -> Self {
892        unsafe {
893            // SAFETY: value is valid UTF-8
894            JavaString::from_semi_utf8_unchecked(value.into_bytes())
895        }
896    }
897}
898
899impl From<&String> for JavaString {
900    #[inline]
901    fn from(value: &String) -> Self {
902        Self::from(value.clone())
903    }
904}
905
906impl From<&JavaString> for JavaString {
907    #[inline]
908    fn from(value: &JavaString) -> Self {
909        value.clone()
910    }
911}
912
913impl From<&mut str> for JavaString {
914    #[inline]
915    fn from(value: &mut str) -> Self {
916        Self::from(&*value)
917    }
918}
919
920impl From<&str> for JavaString {
921    #[inline]
922    fn from(value: &str) -> Self {
923        Self::from(value.to_owned())
924    }
925}
926
927impl From<&mut JavaStr> for JavaString {
928    #[inline]
929    fn from(value: &mut JavaStr) -> Self {
930        Self::from(&*value)
931    }
932}
933
934impl From<&JavaStr> for JavaString {
935    #[inline]
936    fn from(value: &JavaStr) -> Self {
937        value.to_owned()
938    }
939}
940
941impl From<Box<str>> for JavaString {
942    #[inline]
943    fn from(value: Box<str>) -> Self {
944        Self::from(value.into_string())
945    }
946}
947
948impl From<Box<JavaStr>> for JavaString {
949    #[inline]
950    fn from(value: Box<JavaStr>) -> Self {
951        value.into_string()
952    }
953}
954
955impl<'a> From<Cow<'a, str>> for JavaString {
956    #[inline]
957    fn from(value: Cow<'a, str>) -> Self {
958        Self::from(value.into_owned())
959    }
960}
961
962impl<'a> From<Cow<'a, JavaStr>> for JavaString {
963    #[inline]
964    fn from(value: Cow<'a, JavaStr>) -> Self {
965        value.into_owned()
966    }
967}
968
969impl From<JavaString> for Arc<JavaStr> {
970    #[inline]
971    fn from(value: JavaString) -> Self {
972        Arc::from(&value[..])
973    }
974}
975
976impl From<JavaString> for Cow<'_, JavaStr> {
977    #[inline]
978    fn from(value: JavaString) -> Self {
979        Cow::Owned(value)
980    }
981}
982
983impl From<JavaString> for Rc<JavaStr> {
984    #[inline]
985    fn from(value: JavaString) -> Self {
986        Rc::from(&value[..])
987    }
988}
989
990impl From<JavaString> for Vec<u8> {
991    #[inline]
992    fn from(value: JavaString) -> Self {
993        value.into_bytes()
994    }
995}
996
997impl From<char> for JavaString {
998    #[inline]
999    fn from(value: char) -> Self {
1000        Self::from(value.encode_utf8(&mut [0; 4]))
1001    }
1002}
1003
1004impl From<JavaCodePoint> for JavaString {
1005    #[inline]
1006    fn from(value: JavaCodePoint) -> Self {
1007        unsafe {
1008            // SAFETY: we're encoding into semi-valid UTF-8
1009            JavaString::from_semi_utf8_unchecked(value.encode_semi_utf8(&mut [0; 4]).to_vec())
1010        }
1011    }
1012}
1013
1014impl TryFrom<Vec<u8>> for JavaString {
1015    type Error = FromUtf8Error;
1016
1017    #[inline]
1018    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
1019        JavaString::from_semi_utf8(value)
1020    }
1021}
1022
1023impl TryFrom<JavaString> for String {
1024    type Error = Utf8Error;
1025
1026    #[inline]
1027    fn try_from(value: JavaString) -> Result<Self, Self::Error> {
1028        value.into_string()
1029    }
1030}
1031
1032impl FromIterator<char> for JavaString {
1033    #[inline]
1034    fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
1035        let mut buf = JavaString::new();
1036        buf.extend(iter);
1037        buf
1038    }
1039}
1040
1041impl<'a> FromIterator<&'a char> for JavaString {
1042    #[inline]
1043    fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
1044        let mut buf = JavaString::new();
1045        buf.extend(iter);
1046        buf
1047    }
1048}
1049
1050impl FromIterator<JavaCodePoint> for JavaString {
1051    #[inline]
1052    fn from_iter<T: IntoIterator<Item = JavaCodePoint>>(iter: T) -> Self {
1053        let mut buf = JavaString::new();
1054        buf.extend(iter);
1055        buf
1056    }
1057}
1058
1059impl<'a> FromIterator<&'a JavaCodePoint> for JavaString {
1060    #[inline]
1061    fn from_iter<T: IntoIterator<Item = &'a JavaCodePoint>>(iter: T) -> Self {
1062        let mut buf = JavaString::new();
1063        buf.extend(iter);
1064        buf
1065    }
1066}
1067
1068impl<'a> FromIterator<&'a str> for JavaString {
1069    #[inline]
1070    fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
1071        let mut buf = JavaString::new();
1072        buf.extend(iter);
1073        buf
1074    }
1075}
1076
1077impl<'a> FromIterator<&'a JavaStr> for JavaString {
1078    #[inline]
1079    fn from_iter<T: IntoIterator<Item = &'a JavaStr>>(iter: T) -> Self {
1080        let mut buf = JavaString::new();
1081        buf.extend(iter);
1082        buf
1083    }
1084}
1085
1086impl FromIterator<String> for JavaString {
1087    fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
1088        let mut iterator = iter.into_iter();
1089
1090        match iterator.next() {
1091            None => JavaString::new(),
1092            Some(buf) => {
1093                let mut buf = JavaString::from(buf);
1094                buf.extend(iterator);
1095                buf
1096            }
1097        }
1098    }
1099}
1100
1101impl FromIterator<JavaString> for JavaString {
1102    fn from_iter<T: IntoIterator<Item = JavaString>>(iter: T) -> Self {
1103        let mut iterator = iter.into_iter();
1104
1105        match iterator.next() {
1106            None => JavaString::new(),
1107            Some(mut buf) => {
1108                buf.extend(iterator);
1109                buf
1110            }
1111        }
1112    }
1113}
1114
1115impl FromIterator<Box<str>> for JavaString {
1116    #[inline]
1117    fn from_iter<T: IntoIterator<Item = Box<str>>>(iter: T) -> Self {
1118        let mut buf = JavaString::new();
1119        buf.extend(iter);
1120        buf
1121    }
1122}
1123
1124impl FromIterator<Box<JavaStr>> for JavaString {
1125    #[inline]
1126    fn from_iter<T: IntoIterator<Item = Box<JavaStr>>>(iter: T) -> Self {
1127        let mut buf = JavaString::new();
1128        buf.extend(iter);
1129        buf
1130    }
1131}
1132
1133impl<'a> FromIterator<Cow<'a, str>> for JavaString {
1134    #[inline]
1135    fn from_iter<T: IntoIterator<Item = Cow<'a, str>>>(iter: T) -> Self {
1136        let mut buf = JavaString::new();
1137        buf.extend(iter);
1138        buf
1139    }
1140}
1141
1142impl<'a> FromIterator<Cow<'a, JavaStr>> for JavaString {
1143    #[inline]
1144    fn from_iter<T: IntoIterator<Item = Cow<'a, JavaStr>>>(iter: T) -> Self {
1145        let mut buf = JavaString::new();
1146        buf.extend(iter);
1147        buf
1148    }
1149}
1150
1151impl FromStr for JavaString {
1152    type Err = Infallible;
1153
1154    #[inline]
1155    fn from_str(s: &str) -> Result<Self, Self::Err> {
1156        Ok(Self::from(s))
1157    }
1158}
1159
1160impl Hash for JavaString {
1161    #[inline]
1162    fn hash<H: Hasher>(&self, state: &mut H) {
1163        (**self).hash(state)
1164    }
1165}
1166
1167impl Index<Range<usize>> for JavaString {
1168    type Output = JavaStr;
1169
1170    #[inline]
1171    fn index(&self, index: Range<usize>) -> &Self::Output {
1172        &self[..][index]
1173    }
1174}
1175
1176impl Index<RangeFrom<usize>> for JavaString {
1177    type Output = JavaStr;
1178
1179    #[inline]
1180    fn index(&self, index: RangeFrom<usize>) -> &Self::Output {
1181        &self[..][index]
1182    }
1183}
1184
1185impl Index<RangeFull> for JavaString {
1186    type Output = JavaStr;
1187
1188    #[inline]
1189    fn index(&self, _index: RangeFull) -> &Self::Output {
1190        self.as_java_str()
1191    }
1192}
1193
1194impl Index<RangeInclusive<usize>> for JavaString {
1195    type Output = JavaStr;
1196
1197    #[inline]
1198    fn index(&self, index: RangeInclusive<usize>) -> &Self::Output {
1199        &self[..][index]
1200    }
1201}
1202
1203impl Index<RangeTo<usize>> for JavaString {
1204    type Output = JavaStr;
1205
1206    #[inline]
1207    fn index(&self, index: RangeTo<usize>) -> &Self::Output {
1208        &self[..][index]
1209    }
1210}
1211
1212impl Index<RangeToInclusive<usize>> for JavaString {
1213    type Output = JavaStr;
1214
1215    #[inline]
1216    fn index(&self, index: RangeToInclusive<usize>) -> &Self::Output {
1217        &self[..][index]
1218    }
1219}
1220
1221impl IndexMut<Range<usize>> for JavaString {
1222    #[inline]
1223    fn index_mut(&mut self, index: Range<usize>) -> &mut Self::Output {
1224        &mut self[..][index]
1225    }
1226}
1227
1228impl IndexMut<RangeFrom<usize>> for JavaString {
1229    #[inline]
1230    fn index_mut(&mut self, index: RangeFrom<usize>) -> &mut Self::Output {
1231        &mut self[..][index]
1232    }
1233}
1234
1235impl IndexMut<RangeFull> for JavaString {
1236    #[inline]
1237    fn index_mut(&mut self, _index: RangeFull) -> &mut Self::Output {
1238        self.as_mut_java_str()
1239    }
1240}
1241
1242impl IndexMut<RangeInclusive<usize>> for JavaString {
1243    #[inline]
1244    fn index_mut(&mut self, index: RangeInclusive<usize>) -> &mut Self::Output {
1245        &mut self[..][index]
1246    }
1247}
1248
1249impl IndexMut<RangeTo<usize>> for JavaString {
1250    #[inline]
1251    fn index_mut(&mut self, index: RangeTo<usize>) -> &mut Self::Output {
1252        &mut self[..][index]
1253    }
1254}
1255
1256impl IndexMut<RangeToInclusive<usize>> for JavaString {
1257    #[inline]
1258    fn index_mut(&mut self, index: RangeToInclusive<usize>) -> &mut Self::Output {
1259        &mut self[..][index]
1260    }
1261}
1262
1263impl PartialEq<str> for JavaString {
1264    #[inline]
1265    fn eq(&self, other: &str) -> bool {
1266        self[..] == other
1267    }
1268}
1269
1270impl PartialEq<JavaString> for str {
1271    #[inline]
1272    fn eq(&self, other: &JavaString) -> bool {
1273        self == other[..]
1274    }
1275}
1276
1277impl<'a> PartialEq<&'a str> for JavaString {
1278    #[inline]
1279    fn eq(&self, other: &&'a str) -> bool {
1280        self == *other
1281    }
1282}
1283
1284impl PartialEq<JavaString> for &str {
1285    #[inline]
1286    fn eq(&self, other: &JavaString) -> bool {
1287        *self == other
1288    }
1289}
1290
1291impl PartialEq<String> for JavaString {
1292    #[inline]
1293    fn eq(&self, other: &String) -> bool {
1294        &self[..] == other
1295    }
1296}
1297
1298impl PartialEq<JavaString> for String {
1299    #[inline]
1300    fn eq(&self, other: &JavaString) -> bool {
1301        self == &other[..]
1302    }
1303}
1304
1305impl PartialEq<JavaStr> for JavaString {
1306    #[inline]
1307    fn eq(&self, other: &JavaStr) -> bool {
1308        self[..] == other
1309    }
1310}
1311
1312impl<'a> PartialEq<&'a JavaStr> for JavaString {
1313    #[inline]
1314    fn eq(&self, other: &&'a JavaStr) -> bool {
1315        self == *other
1316    }
1317}
1318
1319impl<'a> PartialEq<Cow<'a, str>> for JavaString {
1320    #[inline]
1321    fn eq(&self, other: &Cow<'a, str>) -> bool {
1322        &self[..] == other
1323    }
1324}
1325
1326impl PartialEq<JavaString> for Cow<'_, str> {
1327    #[inline]
1328    fn eq(&self, other: &JavaString) -> bool {
1329        self == &other[..]
1330    }
1331}
1332
1333impl<'a> PartialEq<Cow<'a, JavaStr>> for JavaString {
1334    #[inline]
1335    fn eq(&self, other: &Cow<'a, JavaStr>) -> bool {
1336        &self[..] == other
1337    }
1338}
1339
1340impl PartialEq<JavaString> for Cow<'_, JavaStr> {
1341    #[inline]
1342    fn eq(&self, other: &JavaString) -> bool {
1343        self == &other[..]
1344    }
1345}
1346
1347impl Write for JavaString {
1348    #[inline]
1349    fn write_str(&mut self, s: &str) -> std::fmt::Result {
1350        self.push_str(s);
1351        Ok(())
1352    }
1353
1354    #[inline]
1355    fn write_char(&mut self, c: char) -> std::fmt::Result {
1356        self.push(c);
1357        Ok(())
1358    }
1359}
1360
1361pub struct Drain<'a> {
1362    string: *mut JavaString,
1363    start: usize,
1364    end: usize,
1365    iter: Chars<'a>,
1366}
1367
1368impl Debug for Drain<'_> {
1369    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1370        f.debug_tuple("Drain").field(&self.as_str()).finish()
1371    }
1372}
1373
1374unsafe impl Sync for Drain<'_> {}
1375unsafe impl Send for Drain<'_> {}
1376
1377impl Drop for Drain<'_> {
1378    #[inline]
1379    fn drop(&mut self) {
1380        unsafe {
1381            // Use Vec::drain. "Reaffirm" the bounds checks to avoid
1382            // panic code being inserted again.
1383            let self_vec = (*self.string).as_mut_vec();
1384            if self.start <= self.end && self.end <= self_vec.len() {
1385                self_vec.drain(self.start..self.end);
1386            }
1387        }
1388    }
1389}
1390
1391impl AsRef<JavaStr> for Drain<'_> {
1392    #[inline]
1393    fn as_ref(&self) -> &JavaStr {
1394        self.as_str()
1395    }
1396}
1397
1398impl AsRef<[u8]> for Drain<'_> {
1399    #[inline]
1400    fn as_ref(&self) -> &[u8] {
1401        self.as_str().as_bytes()
1402    }
1403}
1404
1405impl Drain<'_> {
1406    #[inline]
1407    #[must_use]
1408    pub fn as_str(&self) -> &JavaStr {
1409        self.iter.as_str()
1410    }
1411}
1412
1413impl Iterator for Drain<'_> {
1414    type Item = JavaCodePoint;
1415
1416    #[inline]
1417    fn next(&mut self) -> Option<JavaCodePoint> {
1418        self.iter.next()
1419    }
1420
1421    #[inline]
1422    fn size_hint(&self) -> (usize, Option<usize>) {
1423        self.iter.size_hint()
1424    }
1425
1426    #[inline]
1427    fn last(mut self) -> Option<JavaCodePoint> {
1428        self.next_back()
1429    }
1430}
1431
1432impl DoubleEndedIterator for Drain<'_> {
1433    #[inline]
1434    fn next_back(&mut self) -> Option<Self::Item> {
1435        self.iter.next_back()
1436    }
1437}
1438
1439impl FusedIterator for Drain<'_> {}